1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <string>
20 #include <vector>
21 
22 #include <folly/Expected.h>
23 #include <folly/Range.h>
24 
25 namespace folly {
26 
27 /*
28  * json_pointer
29  *
30  * As described in RFC 6901 "JSON Pointer".
31  *
32  * Implements parsing. Traversal using the pointer over data structures must be
33  * implemented separately.
34  */
35 class json_pointer {
36  public:
37   enum class parse_error {
38     invalid_first_character,
39     invalid_escape_sequence,
40   };
41 
42   class parse_exception : public std::runtime_error {
43     using std::runtime_error::runtime_error;
44   };
45 
46   json_pointer() = default;
47   ~json_pointer() = default;
48 
49   /*
50    * Parse string into vector of unescaped tokens.
51    * Non-throwing and throwing versions.
52    */
53   static Expected<json_pointer, parse_error> try_parse(StringPiece const str);
54 
55   static json_pointer parse(StringPiece const str);
56 
57   /*
58    * Return true if this pointer is proper to prefix to another pointer
59    */
60   bool is_prefix_of(json_pointer const& other) const noexcept;
61 
62   /*
63    * Get access to the parsed tokens for applications that want to traverse
64    * the pointer.
65    */
66   std::vector<std::string> const& tokens() const;
67 
68   friend bool operator==(json_pointer const& lhs, json_pointer const& rhs) {
69     return lhs.tokens_ == rhs.tokens_;
70   }
71 
72   friend bool operator!=(json_pointer const& lhs, json_pointer const& rhs) {
73     return lhs.tokens_ != rhs.tokens_;
74   }
75 
76  private:
77   explicit json_pointer(std::vector<std::string>) noexcept;
78 
79   /*
80    * Unescape the specified escape sequences, returns false if incorrect
81    */
82   static bool unescape(std::string&);
83 
84   std::vector<std::string> tokens_;
85 };
86 
87 } // namespace folly
88