1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 2015 Couchbase, Inc 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #if !defined(SUBDOC_PATH_H) && defined(__cplusplus) 19 #define SUBDOC_PATH_H 20 21 #include "subdoc-api.h" 22 #include "jsonsl_header.h" 23 #include <string> 24 #include <list> 25 26 27 typedef jsonsl_jpr_component_st PathComponent; 28 29 class PathComponentInfo : public jsonsl_jpr_st { 30 public: PathComponentInfo(PathComponent *comps = NULL, size_t n = 0)31 PathComponentInfo(PathComponent *comps = NULL, size_t n = 0) { 32 components = comps; 33 ncomponents = n; 34 basestr = NULL; 35 orig = NULL; 36 norig = 0; 37 match_type = 0; 38 } 39 size() const40 size_t size() const { return ncomponents; } 41 empty() const42 bool empty() const { return size() == 0; } 43 operator [](size_t ix) const44 PathComponent& operator[](size_t ix) const { return get_component(ix); } get_component(size_t ix) const45 PathComponent& get_component(size_t ix) const { return components[ix]; } back() const46 PathComponent& back() const { return get_component(size()-1); } 47 48 /**Adds a component (without bounds checking) 49 * @return the newly added component*/ add(jsonsl_jpr_type_t ptype)50 PathComponent& add(jsonsl_jpr_type_t ptype) { 51 PathComponent& ret = get_component(size()); 52 ret.ptype = ptype; 53 ncomponents++; 54 return ret; 55 } 56 pop()57 void pop() { 58 ncomponents--; 59 } 60 61 typedef PathComponent *iterator; begin() const62 iterator begin() const { return components; } end() const63 iterator end() const { return components + size(); } 64 }; 65 66 namespace Subdoc { 67 /** 68 * Path limits: 69 * 70 * Path limits are designed to avoid abuse of the server by making paths too 71 * deep. The jsonsl parser has a fixed limit of depth (adjustable at runtime, 72 * but it is still fixed when allocating it). 73 * 74 * In the context of JSONSL, each JSON document contains an ephemeral "root" 75 * object which is at level 0. The actual top-level object (the list or object) 76 * is considered to be at level 1, and any of its children are considered to be 77 * level 2 and so on. Thus for example 78 * 79 * @code 80 * L0 81 * L1 82 * { 83 * L2 84 * "foo" 85 * : 86 * "bar" 87 * } 88 * @endcode 89 * 90 * and so on. 91 * 92 * It also follows that a maximum depth of 1 only allows a top level (empty) 93 * object. 94 * 95 */ 96 class Limits { 97 public: 98 static const size_t MAX_COMPONENTS = 32; 99 static const size_t PARSER_DEPTH = MAX_COMPONENTS + 1; 100 static const size_t PATH_COMPONENTS_ALLOC = MAX_COMPONENTS + 1; 101 }; 102 103 class Path : public PathComponentInfo { 104 public: 105 typedef PathComponent Component; 106 typedef PathComponentInfo CompInfo; 107 108 Path(); 109 ~Path(); 110 void clear(); 111 int parse(const char *, size_t); parse(const char *s)112 int parse(const char *s) { return parse(s, strlen(s)); } parse(const std::string& s)113 int parse(const std::string& s) { return parse(s.c_str(), s.size()); } 114 115 Component components_s[Limits::PATH_COMPONENTS_ALLOC]; 116 jsonsl_error_t add_array_index(long ixnum); 117 bool has_negix; /* True if there is a negative array index in the path */ 118 private: 119 inline const char * convert_escaped(const char *src, size_t &len); 120 inline int add_num_component(const char *component, size_t len); 121 inline int add_str_component(const char *component, size_t len, int n_backtick); 122 inline int parse_bracket(const char *path, size_t len, size_t *n_comsumed); 123 inline int parse_string(const char *path, size_t len, size_t *n_consumed); 124 125 std::list<std::string*> m_cached; 126 std::list<std::string*> m_used; 127 }; 128 } 129 130 #endif 131