Home | History | Annotate | Download | only in gn
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "tools/gn/escape.h"
      6 
      7 #include "base/containers/stack_container.h"
      8 
      9 namespace {
     10 
     11 template<typename DestString>
     12 void EscapeStringToString(const base::StringPiece& str,
     13                           const EscapeOptions& options,
     14                           DestString* dest,
     15                           bool* needed_quoting) {
     16   bool used_quotes = false;
     17 
     18   for (size_t i = 0; i < str.size(); i++) {
     19     if (str[i] == '$' && (options.mode & ESCAPE_NINJA)) {
     20       // Escape dollars signs since ninja treats these specially.
     21       dest->push_back('$');
     22       dest->push_back('$');
     23     } else if (str[i] == '"' && (options.mode & ESCAPE_SHELL)) {
     24       // Escape quotes with backslashes for the command-line (Ninja doesn't
     25       // care).
     26       dest->push_back('\\');
     27       dest->push_back('"');
     28     } else if (str[i] == ' ') {
     29       if (options.mode & ESCAPE_NINJA) {
     30         // For Ninja just escape spaces with $.
     31         dest->push_back('$');
     32       }
     33       if (options.mode & ESCAPE_SHELL) {
     34         // For the shell, quote the whole string.
     35         if (needed_quoting)
     36           *needed_quoting = true;
     37         if (!options.inhibit_quoting) {
     38           if (!used_quotes) {
     39             used_quotes = true;
     40             dest->insert(dest->begin(), '"');
     41           }
     42         }
     43       }
     44       dest->push_back(' ');
     45     } else if (str[i] == '\'' && (options.mode & ESCAPE_JSON)) {
     46       dest->push_back('\\');
     47       dest->push_back('\'');
     48 #if defined(OS_WIN)
     49     } else if (str[i] == '/' && options.convert_slashes) {
     50       // Convert slashes on Windows if requested.
     51       dest->push_back('\\');
     52 #else
     53     } else if (str[i] == '\\' && (options.mode & ESCAPE_SHELL)) {
     54       // For non-Windows shell, escape backslashes.
     55       dest->push_back('\\');
     56       dest->push_back('\\');
     57 #endif
     58     } else if (str[i] == '\\' && (options.mode & ESCAPE_JSON)) {
     59       dest->push_back('\\');
     60       dest->push_back('\\');
     61     } else {
     62       dest->push_back(str[i]);
     63     }
     64   }
     65 
     66   if (used_quotes)
     67     dest->push_back('"');
     68 }
     69 
     70 }  // namespace
     71 
     72 std::string EscapeString(const base::StringPiece& str,
     73                          const EscapeOptions& options,
     74                          bool* needed_quoting) {
     75   std::string result;
     76   result.reserve(str.size() + 4);  // Guess we'll add a couple of extra chars.
     77   EscapeStringToString(str, options, &result, needed_quoting);
     78   return result;
     79 }
     80 
     81 void EscapeStringToStream(std::ostream& out,
     82                           const base::StringPiece& str,
     83                           const EscapeOptions& options) {
     84   // Escape to a stack buffer and then write out to the stream.
     85   base::StackVector<char, 256> result;
     86   result->reserve(str.size() + 4);  // Guess we'll add a couple of extra chars.
     87   EscapeStringToString(str, options, &result.container(), NULL);
     88   if (!result->empty())
     89     out.write(result->data(), result->size());
     90 }
     91