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