1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "utils/strings/append.h"
18
19 #include <stdarg.h>
20
21 #include <cstring>
22 #include <string>
23 #include <vector>
24
25 namespace libtextclassifier3 {
26 namespace strings {
27
SStringAppendV(std::string * strp,int bufsize,const char * fmt,va_list arglist)28 void SStringAppendV(std::string *strp, int bufsize, const char *fmt,
29 va_list arglist) {
30 int capacity = bufsize;
31 if (capacity <= 0) {
32 va_list backup;
33 va_copy(backup, arglist);
34 capacity = vsnprintf(nullptr, 0, fmt, backup);
35 va_end(arglist);
36 }
37
38 size_t start = strp->size();
39 strp->resize(strp->size() + capacity + 1);
40
41 int written = vsnprintf(&(*strp)[start], capacity + 1, fmt, arglist);
42 va_end(arglist);
43 strp->resize(start + std::min(capacity, written));
44 }
45
SStringAppendF(std::string * strp,int bufsize,const char * fmt,...)46 void SStringAppendF(std::string *strp,
47 int bufsize,
48 const char *fmt, ...) {
49 va_list arglist;
50 va_start(arglist, fmt);
51 SStringAppendV(strp, bufsize, fmt, arglist);
52 }
53
StringPrintf(const char * fmt,...)54 std::string StringPrintf(const char* fmt, ...) {
55 std::string s;
56 va_list arglist;
57 va_start(arglist, fmt);
58 SStringAppendV(&s, 0, fmt, arglist);
59 return s;
60 }
61
JoinStrings(const char * delim,const std::vector<std::string> & vec)62 std::string JoinStrings(const char *delim,
63 const std::vector<std::string> &vec) {
64 int delim_len = strlen(delim);
65
66 // Calc size.
67 int out_len = 0;
68 for (size_t i = 0; i < vec.size(); i++) {
69 out_len += vec[i].size() + delim_len;
70 }
71
72 // Write out.
73 std::string ret;
74 ret.reserve(out_len);
75 for (size_t i = 0; i < vec.size(); i++) {
76 ret.append(vec[i]);
77 ret.append(delim, delim_len);
78 }
79
80 // Strip last delimiter.
81 if (!ret.empty()) {
82 // Must be at least delim_len.
83 ret.resize(ret.size() - delim_len);
84 }
85 return ret;
86 }
87
88 } // namespace strings
89 } // namespace libtextclassifier3
90