1 // Copyright (C) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "icing/legacy/core/icing-string-util.h"
15
16 #include <stdarg.h>
17 #include <stddef.h>
18 #include <stdint.h>
19 #include <stdio.h>
20
21 #include <algorithm>
22 #include <string>
23
24 #include "icing/legacy/portable/icing-zlib.h"
25 #include "icing/util/logging.h"
26
27 namespace icing {
28 namespace lib {
29
UpdateCrc32(uint32_t crc,const char * str,int len)30 uint32_t IcingStringUtil::UpdateCrc32(uint32_t crc, const char *str, int len) {
31 if (len > 0) {
32 crc = ~crc32(~crc, reinterpret_cast<const Bytef *>(str), len);
33 }
34 return crc;
35 }
36
UpdateAtPositionCrc32(uint32_t crc,int orig_len,int offset,const char * xored_str,int len)37 uint32_t IcingStringUtil::UpdateAtPositionCrc32(uint32_t crc, int orig_len,
38 int offset,
39 const char *xored_str,
40 int len) {
41 // For appending, use UpdateCrc32.
42 if (offset + len > orig_len) {
43 ICING_LOG(FATAL) << "offset: " << offset << " length: " << len
44 << "original_length: " << orig_len;
45 }
46
47 // We have CRC(A|U|B) and we want CRC(A|V|B) where U is the slice
48 // that updated to V.
49 //
50 // Then if xored_str = X = U ^ V:
51 //
52 // CRC(A|V|B) = CRC(0_lenA|X|0_lenB ^ A|U|B)
53 // = CRC(0_lenA|X|0_lenB) ^ CRC(A|U|B)
54 // = CRC_COMBINE(CRC(0_lenA), CRC_COMBINE(CRC(X), CRC(0_lenB)) ^ CRC(A|U|B)
55 //
56 // But CRC(0s) = 0, and CRC_COMBINE(0, X) = X, so this becomes
57 // = CRC_COMBINE(CRC(X), CRC(0_lenB)) ^ CRC(A|U|B)
58 uint32_t update_crc = UpdateCrc32(0, xored_str, len);
59 update_crc = crc32_combine(update_crc, 0, orig_len - (offset + len));
60 return crc ^ update_crc;
61 }
62
SStringAppendV(std::string * strp,int bufsize,const char * fmt,va_list arglist)63 void IcingStringUtil::SStringAppendV(std::string *strp, int bufsize,
64 const char *fmt, va_list arglist) {
65 int capacity = bufsize;
66 if (capacity <= 0) {
67 va_list backup;
68 va_copy(backup, arglist);
69 capacity = vsnprintf(nullptr, 0, fmt, backup);
70 va_end(arglist);
71 }
72
73 size_t start = strp->size();
74 strp->resize(strp->size() + capacity + 1);
75
76 int written = vsnprintf(&(*strp)[start], capacity + 1, fmt, arglist);
77 va_end(arglist);
78 strp->resize(start + std::min(capacity, written));
79 }
80
SStringAppendF(std::string * strp,int bufsize,const char * fmt,...)81 void IcingStringUtil::SStringAppendF(std::string *strp, int bufsize,
82 const char *fmt, ...) {
83 va_list arglist;
84 va_start(arglist, fmt);
85 SStringAppendV(strp, bufsize, fmt, arglist);
86 }
87
StringPrintf(const char * fmt,...)88 std::string IcingStringUtil::StringPrintf(const char *fmt, ...) {
89 std::string s;
90 va_list arglist;
91 va_start(arglist, fmt);
92 SStringAppendV(&s, 0, fmt, arglist);
93 return s;
94 }
95
96 } // namespace lib
97 } // namespace icing
98