Skip to content

Commit 7e648b2

Browse files
Refactor Calculator to use absl::string_view operations.
This change updates the string manipulation in Calculator::ParseExpression and Calculator::Tokenize to use absl::string_view methods like ConsumePrefix, ConsumeSuffix, StartsWith, EndsWith, and substr, replacing manual pointer arithmetic. This improves readability and reduces potential errors. PiperOrigin-RevId: 912443377
1 parent e96c1ba commit 7e648b2

1 file changed

Lines changed: 35 additions & 31 deletions

File tree

src/rewriter/calculator/calculator.cc

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "absl/strings/ascii.h"
4242
#include "absl/strings/str_format.h"
4343
#include "absl/strings/string_view.h"
44+
#include "absl/strings/strip.h"
4445
#include "base/japanese_util.h"
4546
#include "base/number_util.h"
4647

@@ -327,17 +328,12 @@ std::optional<std::string> Calculator::CalculateString(
327328
std::string normalized_key =
328329
japanese_util::FullWidthAsciiToHalfWidthAscii(key);
329330

330-
absl::string_view expression_body;
331-
if (normalized_key.front() == '=') {
332-
// Expression starts with '='.
333-
expression_body =
334-
absl::string_view(normalized_key.data() + 1, normalized_key.size() - 1);
335-
} else if (normalized_key.back() == '=') {
336-
// Expression is ended with '='.
337-
expression_body =
338-
absl::string_view(normalized_key.data(), normalized_key.size() - 1);
339-
} else {
340-
// Expression does not start nor end with '='.
331+
if (normalized_key.starts_with('=') && normalized_key.ends_with('=')) {
332+
return std::nullopt;
333+
}
334+
absl::string_view expression_body = normalized_key;
335+
if (!absl::ConsumePrefix(&expression_body, "=") &&
336+
!absl::ConsumeSuffix(&expression_body, "=")) {
341337
return std::nullopt;
342338
}
343339

@@ -358,72 +354,80 @@ std::optional<std::string> Calculator::CalculateString(
358354

359355
std::optional<Calculator::TokenSequence> Calculator::Tokenize(
360356
absl::string_view expression_body) const {
361-
const char* current = expression_body.data();
362-
const char* end = expression_body.data() + expression_body.size();
363357
int num_operator = 0; // Number of operators or functions appeared
364358
int num_value = 0; // Number of values appeared
365359

366360
TokenSequence tokens;
361+
absl::string_view rest = expression_body;
367362

368-
while (current < end) {
363+
while (!rest.empty()) {
369364
// Skip spaces
370-
while ((*current == ' ') || (*current == '\t')) {
371-
++current;
365+
while (!rest.empty() && (rest.front() == ' ' || rest.front() == '\t')) {
366+
rest.remove_prefix(1);
367+
}
368+
if (rest.empty()) {
369+
break;
372370
}
373-
const char* token_begin = current;
374371

375372
// Read value token
376-
while (((*current >= '0') && (*current <= '9')) || (*current == '.')) {
377-
++current;
373+
size_t value_len = 0;
374+
while (value_len < rest.size() &&
375+
(absl::ascii_isdigit(rest[value_len]) ||
376+
rest[value_len] == '.')) {
377+
++value_len;
378378
}
379-
if (token_begin < current) {
380-
std::string number_token(token_begin, current - token_begin);
379+
if (value_len > 0) {
380+
const absl::string_view number_token = rest.substr(0, value_len);
381381
double value = 0.0;
382382
if (!NumberUtil::SafeStrToDouble(number_token, &value)) {
383383
return std::nullopt;
384384
}
385385
tokens.push_back({TokenType::INTEGER, value});
386386
++num_value;
387+
rest.remove_prefix(value_len);
387388
continue;
388389
}
389390

390391
// Read alphabetical function name token
391-
if (absl::ascii_isalpha(*current)) {
392-
while (current < end && absl::ascii_isalpha(*current)) {
393-
++current;
392+
if (absl::ascii_isalpha(rest.front())) {
393+
size_t func_len = 0;
394+
while (func_len < rest.size() && absl::ascii_isalpha(rest[func_len])) {
395+
++func_len;
394396
}
395-
std::string name(token_begin, current - token_begin);
397+
std::string name(rest.data(), func_len);
396398
absl::AsciiStrToLower(&name);
397399
const auto func_it = operator_map_.find(name);
398400
if (func_it != operator_map_.end()) {
399401
tokens.push_back({func_it->second, 0.0});
402+
rest.remove_prefix(func_len);
400403
++num_operator;
401404
continue;
402405
}
403406
return std::nullopt;
404407
}
405408

406409
// Read operator token
410+
bool matched_operator = false;
407411
for (size_t length = 1; length <= kMaxLengthOfOperator; ++length) {
408-
if (current + length > end) {
409-
// Invalid token
410-
return std::nullopt;
412+
if (length > rest.size()) {
413+
break;
411414
}
412-
absl::string_view window(current, length);
415+
const absl::string_view window = rest.substr(0, length);
413416
const auto op_it = operator_map_.find(window);
414417
if (op_it == operator_map_.end()) {
415418
continue;
416419
}
417420
tokens.push_back({op_it->second, 0.0});
418-
current += length;
421+
rest.remove_prefix(length);
422+
matched_operator = true;
419423
// Does not count parenthesis as an operator.
420424
if ((op_it->second != TokenType::LP) &&
421425
(op_it->second != TokenType::RP)) {
422426
++num_operator;
423427
}
424428
break;
425429
}
426-
if (token_begin < current) {
430+
if (matched_operator) {
427431
continue;
428432
}
429433

0 commit comments

Comments
 (0)