field_mask_utility.cc
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
32 
36 
37 #include <google/protobuf/port_def.inc>
38 
39 namespace google {
40 namespace protobuf {
41 namespace util {
42 namespace converter {
43 
44 namespace {
45 
46 // Appends a FieldMask path segment to a prefix.
47 std::string AppendPathSegmentToPrefix(StringPiece prefix,
48  StringPiece segment) {
49  if (prefix.empty()) {
50  return std::string(segment);
51  }
52  if (segment.empty()) {
53  return std::string(prefix);
54  }
55  // If the segment is a map key, appends it to the prefix without the ".".
56  if (HasPrefixString(segment, "[\"")) {
57  return StrCat(prefix, segment);
58  }
59  return StrCat(prefix, ".", segment);
60 }
61 
62 } // namespace
63 
65  ConverterCallback converter) {
66  std::string result;
67  result.reserve(path.size() << 1);
68 
69  bool is_quoted = false;
70  bool is_escaping = false;
71  int current_segment_start = 0;
72 
73  // Loops until 1 passed the end of the input to make handling the last
74  // segment easier.
75  for (size_t i = 0; i <= path.size(); ++i) {
76  // Outputs quoted string as-is.
77  if (is_quoted) {
78  if (i == path.size()) {
79  break;
80  }
81  result.push_back(path[i]);
82  if (is_escaping) {
83  is_escaping = false;
84  } else if (path[i] == '\\') {
85  is_escaping = true;
86  } else if (path[i] == '\"') {
87  current_segment_start = i + 1;
88  is_quoted = false;
89  }
90  continue;
91  }
92  if (i == path.size() || path[i] == '.' || path[i] == '(' ||
93  path[i] == ')' || path[i] == '\"') {
94  result += converter(
95  path.substr(current_segment_start, i - current_segment_start));
96  if (i < path.size()) {
97  result.push_back(path[i]);
98  }
99  current_segment_start = i + 1;
100  }
101  if (i < path.size() && path[i] == '\"') {
102  is_quoted = true;
103  }
104  }
105  return result;
106 }
107 
109  PathSinkCallback path_sink) {
110  std::stack<std::string> prefix;
111  int length = paths.length();
112  int previous_position = 0;
113  bool in_map_key = false;
114  bool is_escaping = false;
115  // Loops until 1 passed the end of the input to make the handle of the last
116  // segment easier.
117  for (int i = 0; i <= length; ++i) {
118  if (i != length) {
119  // Skips everything in a map key until we hit the end of it, which is
120  // marked by an un-escaped '"' immediately followed by a ']'.
121  if (in_map_key) {
122  if (is_escaping) {
123  is_escaping = false;
124  continue;
125  }
126  if (paths[i] == '\\') {
127  is_escaping = true;
128  continue;
129  }
130  if (paths[i] != '\"') {
131  continue;
132  }
133  // Un-escaped '"' must be followed with a ']'.
134  if (i >= length - 1 || paths[i + 1] != ']') {
135  return util::Status(
137  StrCat(
138  "Invalid FieldMask '", paths,
139  "'. Map keys should be represented as [\"some_key\"]."));
140  }
141  // The end of the map key ("\"]") has been found.
142  in_map_key = false;
143  // Skips ']'.
144  i++;
145  // Checks whether the key ends at the end of a path segment.
146  if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
147  paths[i + 1] != ')' && paths[i + 1] != '(') {
148  return util::Status(
150  StrCat(
151  "Invalid FieldMask '", paths,
152  "'. Map keys should be at the end of a path segment."));
153  }
154  is_escaping = false;
155  continue;
156  }
157 
158  // We are not in a map key, look for the start of one.
159  if (paths[i] == '[') {
160  if (i >= length - 1 || paths[i + 1] != '\"') {
161  return util::Status(
163  StrCat(
164  "Invalid FieldMask '", paths,
165  "'. Map keys should be represented as [\"some_key\"]."));
166  }
167  // "[\"" starts a map key.
168  in_map_key = true;
169  i++; // Skips the '\"'.
170  continue;
171  }
172  // If the current character is not a special character (',', '(' or ')'),
173  // continue to the next.
174  if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') {
175  continue;
176  }
177  }
178  // Gets the current segment - sub-string between previous position (after
179  // '(', ')', ',', or the beginning of the input) and the current position.
180  StringPiece segment =
181  paths.substr(previous_position, i - previous_position);
182  std::string current_prefix = prefix.empty() ? "" : prefix.top();
183 
184  if (i < length && paths[i] == '(') {
185  // Builds a prefix and save it into the stack.
186  prefix.push(AppendPathSegmentToPrefix(current_prefix, segment));
187  } else if (!segment.empty()) {
188  // When the current charactor is ')', ',' or the current position has
189  // passed the end of the input, builds and outputs a new paths by
190  // concatenating the last prefix with the current segment.
192  path_sink(AppendPathSegmentToPrefix(current_prefix, segment)));
193  }
194 
195  // Removes the last prefix after seeing a ')'.
196  if (i < length && paths[i] == ')') {
197  if (prefix.empty()) {
198  return util::Status(
200  StrCat("Invalid FieldMask '", paths,
201  "'. Cannot find matching '(' for all ')'."));
202  }
203  prefix.pop();
204  }
205  previous_position = i + 1;
206  }
207  if (in_map_key) {
208  return util::Status(
210  StrCat("Invalid FieldMask '", paths,
211  "'. Cannot find matching ']' for all '['."));
212  }
213  if (!prefix.empty()) {
214  return util::Status(
216  StrCat("Invalid FieldMask '", paths,
217  "'. Cannot find matching ')' for all '('."));
218  }
219  return util::Status();
220 }
221 
222 } // namespace converter
223 } // namespace util
224 } // namespace protobuf
225 } // namespace google
google::protobuf::StringPiece::length
stringpiece_ssize_type length() const
Definition: stringpiece.h:249
google::protobuf::util::converter::DecodeCompactFieldMaskPaths
util::Status DecodeCompactFieldMaskPaths(StringPiece paths, PathSinkCallback path_sink)
Definition: field_mask_utility.cc:108
google::protobuf::StrCat
string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: strutil.cc:1480
length
GLenum GLuint GLenum GLsizei length
Definition: glcorearb.h:2695
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
google::protobuf::StringPiece::substr
StringPiece substr(size_type pos, size_type n=npos) const
Definition: stringpiece.cc:261
google::protobuf::util::converter::ConverterCallback
std::function< std::string(StringPiece)> ConverterCallback
Definition: field_mask_utility.h:49
utility.h
strutil.h
google::protobuf::StringPiece::empty
bool empty() const
Definition: stringpiece.h:250
path
GLsizei const GLchar ** path
Definition: glcorearb.h:3658
prefix
static const char prefix[]
Definition: test_pair_ipc.cpp:26
google::protobuf::StringPiece
Definition: stringpiece.h:180
field_mask_utility.h
status_macros.h
google::protobuf::HasPrefixString
bool HasPrefixString(const string &str, const string &prefix)
Definition: strutil.h:115
google::protobuf::util::error::INVALID_ARGUMENT
@ INVALID_ARGUMENT
Definition: status.h:50
aditof::Status
Status
Status of any operation that the TOF sdk performs.
Definition: status_definitions.h:48
i
int i
Definition: gmock-matchers_test.cc:764
google::protobuf::util::converter::ConvertFieldMaskPath
std::string ConvertFieldMaskPath(const StringPiece path, ConverterCallback converter)
Definition: field_mask_utility.cc:64
google::protobuf::util::Status
Definition: status.h:67
google::protobuf::util::converter::PathSinkCallback
std::function< util::Status(StringPiece)> PathSinkCallback
Definition: field_mask_utility.h:50
RETURN_IF_ERROR
#define RETURN_IF_ERROR(expr)
Definition: status_macros.h:49
google
Definition: data_proto2_to_proto3_util.h:11


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:51