1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker *
4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker *
8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker *
10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker */
16*993b0882SAndroid Build Coastguard Worker
17*993b0882SAndroid Build Coastguard Worker #include "utils/strings/substitute.h"
18*993b0882SAndroid Build Coastguard Worker
19*993b0882SAndroid Build Coastguard Worker #include <algorithm>
20*993b0882SAndroid Build Coastguard Worker
21*993b0882SAndroid Build Coastguard Worker #include "utils/base/logging.h"
22*993b0882SAndroid Build Coastguard Worker
23*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
24*993b0882SAndroid Build Coastguard Worker namespace strings {
25*993b0882SAndroid Build Coastguard Worker
Substitute(const StringPiece format,const std::vector<StringPiece> & args,std::string * output)26*993b0882SAndroid Build Coastguard Worker bool Substitute(const StringPiece format, const std::vector<StringPiece>& args,
27*993b0882SAndroid Build Coastguard Worker std::string* output) {
28*993b0882SAndroid Build Coastguard Worker // Determine total size needed.
29*993b0882SAndroid Build Coastguard Worker size_t size = 0;
30*993b0882SAndroid Build Coastguard Worker for (size_t i = 0; i < format.size(); i++) {
31*993b0882SAndroid Build Coastguard Worker if (format[i] == '$') {
32*993b0882SAndroid Build Coastguard Worker if (i + 1 >= format.size()) {
33*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Invalid format string: " << format.ToString();
34*993b0882SAndroid Build Coastguard Worker return false;
35*993b0882SAndroid Build Coastguard Worker } else if (isdigit(format[i + 1])) {
36*993b0882SAndroid Build Coastguard Worker int index = format[i + 1] - '0';
37*993b0882SAndroid Build Coastguard Worker if (static_cast<size_t>(index) >= args.size()) {
38*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Asked for " << index << ", but only "
39*993b0882SAndroid Build Coastguard Worker << args.size() << " arguments given";
40*993b0882SAndroid Build Coastguard Worker return false;
41*993b0882SAndroid Build Coastguard Worker }
42*993b0882SAndroid Build Coastguard Worker size += args[index].size();
43*993b0882SAndroid Build Coastguard Worker ++i; // Skip next char.
44*993b0882SAndroid Build Coastguard Worker } else if (format[i + 1] == '$') {
45*993b0882SAndroid Build Coastguard Worker ++size;
46*993b0882SAndroid Build Coastguard Worker ++i; // Skip next char.
47*993b0882SAndroid Build Coastguard Worker } else {
48*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Invalid format string: " << format.ToString();
49*993b0882SAndroid Build Coastguard Worker return false;
50*993b0882SAndroid Build Coastguard Worker }
51*993b0882SAndroid Build Coastguard Worker } else {
52*993b0882SAndroid Build Coastguard Worker ++size;
53*993b0882SAndroid Build Coastguard Worker }
54*993b0882SAndroid Build Coastguard Worker }
55*993b0882SAndroid Build Coastguard Worker
56*993b0882SAndroid Build Coastguard Worker if (size == 0) {
57*993b0882SAndroid Build Coastguard Worker output->clear();
58*993b0882SAndroid Build Coastguard Worker return true;
59*993b0882SAndroid Build Coastguard Worker }
60*993b0882SAndroid Build Coastguard Worker
61*993b0882SAndroid Build Coastguard Worker // Build the string.
62*993b0882SAndroid Build Coastguard Worker output->resize(size);
63*993b0882SAndroid Build Coastguard Worker char* target = &(*output)[0];
64*993b0882SAndroid Build Coastguard Worker for (size_t i = 0; i < format.size(); i++) {
65*993b0882SAndroid Build Coastguard Worker if (format[i] == '$') {
66*993b0882SAndroid Build Coastguard Worker if (isdigit(format[i + 1])) {
67*993b0882SAndroid Build Coastguard Worker const StringPiece src = args[format[i + 1] - '0'];
68*993b0882SAndroid Build Coastguard Worker target = std::copy(src.data(), src.data() + src.size(), target);
69*993b0882SAndroid Build Coastguard Worker ++i; // Skip next char.
70*993b0882SAndroid Build Coastguard Worker } else if (format[i + 1] == '$') {
71*993b0882SAndroid Build Coastguard Worker *target++ = '$';
72*993b0882SAndroid Build Coastguard Worker ++i; // Skip next char.
73*993b0882SAndroid Build Coastguard Worker }
74*993b0882SAndroid Build Coastguard Worker } else {
75*993b0882SAndroid Build Coastguard Worker *target++ = format[i];
76*993b0882SAndroid Build Coastguard Worker }
77*993b0882SAndroid Build Coastguard Worker }
78*993b0882SAndroid Build Coastguard Worker return true;
79*993b0882SAndroid Build Coastguard Worker }
80*993b0882SAndroid Build Coastguard Worker
Substitute(const StringPiece format,const std::vector<StringPiece> & args)81*993b0882SAndroid Build Coastguard Worker std::string Substitute(const StringPiece format,
82*993b0882SAndroid Build Coastguard Worker const std::vector<StringPiece>& args) {
83*993b0882SAndroid Build Coastguard Worker std::string result;
84*993b0882SAndroid Build Coastguard Worker if (!Substitute(format, args, &result)) {
85*993b0882SAndroid Build Coastguard Worker return "";
86*993b0882SAndroid Build Coastguard Worker }
87*993b0882SAndroid Build Coastguard Worker return result;
88*993b0882SAndroid Build Coastguard Worker }
89*993b0882SAndroid Build Coastguard Worker
90*993b0882SAndroid Build Coastguard Worker } // namespace strings
91*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3
92