Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: tools/gn/string_utils.cc

Issue 1546393002: Allow \n in GN string literals (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix documentation line Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/parser.cc ('k') | tools/gn/string_utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/string_utils.h" 5 #include "tools/gn/string_utils.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <cctype>
8 9
10 #include "base/strings/string_number_conversions.h"
9 #include "tools/gn/err.h" 11 #include "tools/gn/err.h"
10 #include "tools/gn/input_file.h" 12 #include "tools/gn/input_file.h"
11 #include "tools/gn/parser.h" 13 #include "tools/gn/parser.h"
12 #include "tools/gn/scope.h" 14 #include "tools/gn/scope.h"
13 #include "tools/gn/token.h" 15 #include "tools/gn/token.h"
14 #include "tools/gn/tokenizer.h" 16 #include "tools/gn/tokenizer.h"
15 #include "tools/gn/value.h" 17 #include "tools/gn/value.h"
16 18
17 namespace { 19 namespace {
18 20
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 std::string("\"") + identifier + "\" is not currently in scope."); 126 std::string("\"") + identifier + "\" is not currently in scope.");
125 return false; 127 return false;
126 } 128 }
127 129
128 output->append(value->ToString(false)); 130 output->append(value->ToString(false));
129 return true; 131 return true;
130 } 132 }
131 133
132 // Handles string interpolations: $identifier and ${expression} 134 // Handles string interpolations: $identifier and ${expression}
133 // 135 //
134 // |*i| is the index into |input| of the $. This will be updated to point to 136 // |*i| is the index into |input| after the $. This will be updated to point to
135 // the last character consumed on success. The token is the original string 137 // the last character consumed on success. The token is the original string
136 // to blame on failure. 138 // to blame on failure.
137 // 139 //
138 // On failure, returns false and sets the error. On success, appends the 140 // On failure, returns false and sets the error. On success, appends the
139 // result of the interpolation to |*output|. 141 // result of the interpolation to |*output|.
140 bool AppendStringInterpolation(Scope* scope, 142 bool AppendStringInterpolation(Scope* scope,
141 const Token& token, 143 const Token& token,
142 const char* input, size_t size, 144 const char* input, size_t size,
143 size_t* i, 145 size_t* i,
144 std::string* output, 146 std::string* output,
145 Err* err) { 147 Err* err) {
146 size_t dollars_index = *i; 148 size_t dollars_index = *i - 1;
147 (*i)++;
148 if (*i == size) {
149 *err = ErrInsideStringToken(token, dollars_index, 1, "$ at end of string.",
150 "I was expecting an identifier or {...} after the $.");
151 return false;
152 }
153 149
154 if (input[*i] == '{') { 150 if (input[*i] == '{') {
155 // Bracketed expression. 151 // Bracketed expression.
156 (*i)++; 152 (*i)++;
157 size_t begin_offset = *i; 153 size_t begin_offset = *i;
158 154
159 // Find the closing } and check for non-identifier chars. Don't need to 155 // Find the closing } and check for non-identifier chars. Don't need to
160 // bother checking for the more-restricted first character of an identifier 156 // bother checking for the more-restricted first character of an identifier
161 // since the {} unambiguously denotes the range, and identifiers with 157 // since the {} unambiguously denotes the range, and identifiers with
162 // invalid names just won't be found later. 158 // invalid names just won't be found later.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 192
197 // Find the first non-identifier char following the string. 193 // Find the first non-identifier char following the string.
198 while (*i < size && Tokenizer::IsIdentifierContinuingChar(input[*i])) 194 while (*i < size && Tokenizer::IsIdentifierContinuingChar(input[*i]))
199 (*i)++; 195 (*i)++;
200 size_t end_offset = *i; 196 size_t end_offset = *i;
201 (*i)--; // Back up to mark the last character consumed. 197 (*i)--; // Back up to mark the last character consumed.
202 return AppendInterpolatedIdentifier(scope, token, input, begin_offset, 198 return AppendInterpolatedIdentifier(scope, token, input, begin_offset,
203 end_offset, output, err); 199 end_offset, output, err);
204 } 200 }
205 201
202 // Handles a hex literal: $0xFF
203 //
204 // |*i| is the index into |input| after the $. This will be updated to point to
205 // the last character consumed on success. The token is the original string
206 // to blame on failure.
207 //
208 // On failure, returns false and sets the error. On success, appends the
209 // char with the given hex value to |*output|.
210 bool AppendHexByte(Scope* scope,
211 const Token& token,
212 const char* input, size_t size,
213 size_t* i,
214 std::string* output,
215 Err* err) {
216 size_t dollars_index = *i - 1;
217 // "$0" is already known to exist.
218 if (*i + 3 >= size || input[*i + 1] != 'x' || !std::isxdigit(input[*i + 2]) ||
219 !std::isxdigit(input[*i + 3])) {
220 *err = ErrInsideStringToken(
221 token, dollars_index, *i - dollars_index + 1,
222 "Invalid hex character. Hex values must look like 0xFF.");
223 return false;
224 }
225 int value = 0;
226 if (!base::HexStringToInt(base::StringPiece(&input[*i + 2], 2), &value)) {
227 *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index + 1,
228 "Could not convert hex value.");
229 return false;
230 }
231 *i += 3;
232 output->push_back(value);
brettw 2016/01/05 18:11:04 I'm surprised you can push_back an into on a strin
agrieve 2016/01/05 19:43:19 Yeah, just tried both GCC and clang again but no w
233 return true;
234 }
235
206 } // namespace 236 } // namespace
207 237
208 bool ExpandStringLiteral(Scope* scope, 238 bool ExpandStringLiteral(Scope* scope,
209 const Token& literal, 239 const Token& literal,
210 Value* result, 240 Value* result,
211 Err* err) { 241 Err* err) {
212 DCHECK(literal.type() == Token::STRING); 242 DCHECK(literal.type() == Token::STRING);
213 DCHECK(literal.value().size() > 1); // Should include quotes. 243 DCHECK(literal.value().size() > 1); // Should include quotes.
214 DCHECK(result->type() == Value::STRING); // Should be already set. 244 DCHECK(result->type() == Value::STRING); // Should be already set.
215 245
(...skipping 12 matching lines...) Expand all
228 case '$': 258 case '$':
229 output.push_back(input[i + 1]); 259 output.push_back(input[i + 1]);
230 i++; 260 i++;
231 continue; 261 continue;
232 default: // Everything else has no meaning: pass the literal. 262 default: // Everything else has no meaning: pass the literal.
233 break; 263 break;
234 } 264 }
235 } 265 }
236 output.push_back(input[i]); 266 output.push_back(input[i]);
237 } else if (input[i] == '$') { 267 } else if (input[i] == '$') {
238 if (!AppendStringInterpolation(scope, literal, input, size, &i, 268 i++;
269 if (i == size) {
270 *err = ErrInsideStringToken(literal, i - 1, 1, "$ at end of string.",
271 "I was expecting an identifier, 0xFF, or {...} after the $.");
272 return false;
273 }
274 if (input[i] == '0') {
275 if (!AppendHexByte(scope, literal, input, size, &i, &output, err))
276 return false;
277 } else if (!AppendStringInterpolation(scope, literal, input, size, &i,
239 &output, err)) 278 &output, err))
240 return false; 279 return false;
241 } else { 280 } else {
242 output.push_back(input[i]); 281 output.push_back(input[i]);
243 } 282 }
244 } 283 }
245 return true; 284 return true;
246 } 285 }
OLDNEW
« no previous file with comments | « tools/gn/parser.cc ('k') | tools/gn/string_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698