// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tools/gn/string_utils.h"

#include "tools/gn/err.h"
#include "tools/gn/scope.h"
#include "tools/gn/token.h"
#include "tools/gn/tokenizer.h"
#include "tools/gn/value.h"

namespace {

// Constructs an Err indicating a range inside a string. We assume that the
// token has quotes around it that are not counted by the offset.
Err ErrInsideStringToken(const Token& token, size_t offset, size_t size,
                         const std::string& msg,
                         const std::string& help = std::string()) {
  // The "+1" is skipping over the " at the beginning of the token.
  int int_offset = static_cast<int>(offset);
  Location begin_loc(token.location().file(),
                     token.location().line_number(),
                     token.location().char_offset() + int_offset + 1,
                     token.location().byte() + int_offset + 1);
  Location end_loc(
      token.location().file(),
      token.location().line_number(),
      token.location().char_offset() + int_offset + 1 + static_cast<int>(size),
      token.location().byte() + int_offset + 1 + static_cast<int>(size));
  return Err(LocationRange(begin_loc, end_loc), msg, help);
}

// Given the character input[i] indicating the $ in a string, locates the
// identifier and places its range in |*identifier|, and updates |*i| to
// point to the last character consumed.
//
// On error returns false and sets the error.
bool LocateInlineIdenfitier(const Token& token,
                            const char* input, size_t size,
                            size_t* i,
                            base::StringPiece* identifier,
                            Err* err) {
  size_t dollars_index = *i;
  (*i)++;
  if (*i == size) {
    *err = ErrInsideStringToken(token, dollars_index, 1, "$ at end of string.",
        "I was expecting an identifier after the $.");
    return false;
  }

  bool has_brackets;
  if (input[*i] == '{') {
    (*i)++;
    if (*i == size) {
      *err = ErrInsideStringToken(token, dollars_index, 2,
          "${ at end of string.",
          "I was expecting an identifier inside the ${...}.");
      return false;
    }
    has_brackets = true;
  } else {
    has_brackets = false;
  }

  // First char is special.
  if (!Tokenizer::IsIdentifierFirstChar(input[*i])) {
    *err = ErrInsideStringToken(
        token, dollars_index, *i - dollars_index + 1,
        "$ not followed by an identifier char.",
        "It you want a literal $ use \"\\$\".");
    return false;
  }
  size_t begin_offset = *i;
  (*i)++;

  // Find the first non-identifier char following the string.
  while (*i < size && Tokenizer::IsIdentifierContinuingChar(input[*i]))
    (*i)++;
  size_t end_offset = *i;

  // If we started with a bracket, validate that there's an ending one. Leave
  // *i pointing to the last char we consumed (backing up one).
  if (has_brackets) {
    if (*i == size) {
      *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index,
                                  "Unterminated ${...");
      return false;
    } else if (input[*i] != '}') {
      *err = ErrInsideStringToken(token, *i, 1, "Not an identifier in string expansion.",
          "The contents of ${...} should be an identifier. "
          "This character is out of sorts.");
      return false;
    }
    // We want to consume the bracket but also back up one, so *i is unchanged.
  } else {
    (*i)--;
  }

  *identifier = base::StringPiece(&input[begin_offset],
                                  end_offset - begin_offset);
  return true;
}

bool AppendIdentifierValue(Scope* scope,
                           const Token& token,
                           const base::StringPiece& identifier,
                           std::string* output,
                           Err* err) {
  const Value* value = scope->GetValue(identifier, true);
  if (!value) {
    // We assume the identifier points inside the token.
    *err = ErrInsideStringToken(
        token, identifier.data() - token.value().data() - 1, identifier.size(),
        "Undefined identifier in string expansion.",
        std::string("\"") + identifier + "\" is not currently in scope.");
    return false;
  }

  output->append(value->ToString(false));
  return true;
}

}  // namespace

bool ExpandStringLiteral(Scope* scope,
                         const Token& literal,
                         Value* result,
                         Err* err) {
  DCHECK(literal.type() == Token::STRING);
  DCHECK(literal.value().size() > 1);  // Should include quotes.
  DCHECK(result->type() == Value::STRING);  // Should be already set.

  // The token includes the surrounding quotes, so strip those off.
  const char* input = &literal.value().data()[1];
  size_t size = literal.value().size() - 2;

  std::string& output = result->string_value();
  output.reserve(size);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == '\\') {
      if (i < size - 1) {
        switch (input[i + 1]) {
          case '\\':
          case '"':
          case '$':
            output.push_back(input[i + 1]);
            i++;
            continue;
          default:  // Everything else has no meaning: pass the literal.
            break;
        }
      }
      output.push_back(input[i]);
    } else if (input[i] == '$') {
      base::StringPiece identifier;
      if (!LocateInlineIdenfitier(literal, input, size, &i, &identifier, err))
        return false;
      if (!AppendIdentifierValue(scope, literal, identifier, &output, err))
        return false;
    } else {
      output.push_back(input[i]);
    }
  }
  return true;
}

std::string RemovePrefix(const std::string& str, const std::string& prefix) {
  CHECK(str.size() >= prefix.size() &&
        str.compare(0, prefix.size(), prefix) == 0);
  return str.substr(prefix.size());
}

void TrimTrailingSlash(std::string* str) {
  if (!str->empty()) {
    DCHECK((*str)[str->size() - 1] == '/');
    str->resize(str->size() - 1);
  }
}
