// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <google/protobuf/util/internal/field_mask_utility.h>

#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/status_macros.h>

// Must be included last.
#include <google/protobuf/port_def.inc>

namespace google {
namespace protobuf {
namespace util {
namespace converter {

namespace {

// Appends a FieldMask path segment to a prefix.
std::string AppendPathSegmentToPrefix(StringPiece prefix,
                                      StringPiece segment) {
  if (prefix.empty()) {
    return std::string(segment);
  }
  if (segment.empty()) {
    return std::string(prefix);
  }
  // If the segment is a map key, appends it to the prefix without the ".".
  if (HasPrefixString(segment, "[\"")) {
    return StrCat(prefix, segment);
  }
  return StrCat(prefix, ".", segment);
}

}  // namespace

std::string ConvertFieldMaskPath(const StringPiece path,
                                 ConverterCallback converter) {
  std::string result;
  result.reserve(path.size() << 1);

  bool is_quoted = false;
  bool is_escaping = false;
  int current_segment_start = 0;

  // Loops until 1 passed the end of the input to make handling the last
  // segment easier.
  for (size_t i = 0; i <= path.size(); ++i) {
    // Outputs quoted string as-is.
    if (is_quoted) {
      if (i == path.size()) {
        break;
      }
      result.push_back(path[i]);
      if (is_escaping) {
        is_escaping = false;
      } else if (path[i] == '\\') {
        is_escaping = true;
      } else if (path[i] == '\"') {
        current_segment_start = i + 1;
        is_quoted = false;
      }
      continue;
    }
    if (i == path.size() || path[i] == '.' || path[i] == '(' ||
        path[i] == ')' || path[i] == '\"') {
      result += converter(
          path.substr(current_segment_start, i - current_segment_start));
      if (i < path.size()) {
        result.push_back(path[i]);
      }
      current_segment_start = i + 1;
    }
    if (i < path.size() && path[i] == '\"') {
      is_quoted = true;
    }
  }
  return result;
}

util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
                                         PathSinkCallback path_sink) {
  std::stack<std::string> prefix;
  int length = paths.length();
  int previous_position = 0;
  bool in_map_key = false;
  bool is_escaping = false;
  // Loops until 1 passed the end of the input to make the handle of the last
  // segment easier.
  for (int i = 0; i <= length; ++i) {
    if (i != length) {
      // Skips everything in a map key until we hit the end of it, which is
      // marked by an un-escaped '"' immediately followed by a ']'.
      if (in_map_key) {
        if (is_escaping) {
          is_escaping = false;
          continue;
        }
        if (paths[i] == '\\') {
          is_escaping = true;
          continue;
        }
        if (paths[i] != '\"') {
          continue;
        }
        // Un-escaped '"' must be followed with a ']'.
        if (i >= length - 1 || paths[i + 1] != ']') {
          return util::InvalidArgumentError(StrCat(
              "Invalid FieldMask '", paths,
              "'. Map keys should be represented as [\"some_key\"]."));
        }
        // The end of the map key ("\"]") has been found.
        in_map_key = false;
        // Skips ']'.
        i++;
        // Checks whether the key ends at the end of a path segment.
        if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
            paths[i + 1] != ')' && paths[i + 1] != '(') {
          return util::InvalidArgumentError(StrCat(
              "Invalid FieldMask '", paths,
              "'. Map keys should be at the end of a path segment."));
        }
        is_escaping = false;
        continue;
      }

      // We are not in a map key, look for the start of one.
      if (paths[i] == '[') {
        if (i >= length - 1 || paths[i + 1] != '\"') {
          return util::InvalidArgumentError(StrCat(
              "Invalid FieldMask '", paths,
              "'. Map keys should be represented as [\"some_key\"]."));
        }
        // "[\"" starts a map key.
        in_map_key = true;
        i++;  // Skips the '\"'.
        continue;
      }
      // If the current character is not a special character (',', '(' or ')'),
      // continue to the next.
      if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') {
        continue;
      }
    }
    // Gets the current segment - sub-string between previous position (after
    // '(', ')', ',', or the beginning of the input) and the current position.
    StringPiece segment =
        paths.substr(previous_position, i - previous_position);
    std::string current_prefix = prefix.empty() ? "" : prefix.top();

    if (i < length && paths[i] == '(') {
      // Builds a prefix and save it into the stack.
      prefix.push(AppendPathSegmentToPrefix(current_prefix, segment));
    } else if (!segment.empty()) {
      // When the current character is ')', ',' or the current position has
      // passed the end of the input, builds and outputs a new paths by
      // concatenating the last prefix with the current segment.
      RETURN_IF_ERROR(
          path_sink(AppendPathSegmentToPrefix(current_prefix, segment)));
    }

    // Removes the last prefix after seeing a ')'.
    if (i < length && paths[i] == ')') {
      if (prefix.empty()) {
        return util::InvalidArgumentError(
            StrCat("Invalid FieldMask '", paths,
                         "'. Cannot find matching '(' for all ')'."));
      }
      prefix.pop();
    }
    previous_position = i + 1;
  }
  if (in_map_key) {
    return util::InvalidArgumentError(
        StrCat("Invalid FieldMask '", paths,
                     "'. Cannot find matching ']' for all '['."));
  }
  if (!prefix.empty()) {
    return util::InvalidArgumentError(
        StrCat("Invalid FieldMask '", paths,
                     "'. Cannot find matching ')' for all '('."));
  }
  return util::Status();
}

}  // namespace converter
}  // namespace util
}  // namespace protobuf
}  // namespace google
