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