Coverage Report

Created: 2026-09-03 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sentencepiece/src/util.h
Line
Count
Source
1
// Copyright 2016 Google Inc.
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
15
#ifndef UTIL_H_
16
#define UTIL_H_
17
18
#include <algorithm>
19
#include <cstdint>
20
#include <cstring>
21
#include <memory>
22
#include <random>
23
#include <string>
24
#include <type_traits>
25
#include <vector>
26
27
#include "absl/functional/any_invocable.h"
28
#include "absl/random/random.h"
29
#include "absl/status/status.h"
30
#include "absl/strings/numbers.h"
31
#include "absl/strings/str_cat.h"
32
#include "absl/strings/string_view.h"
33
34
static constexpr uint32_t kUnicodeError = 0xFFFD;
35
36
namespace sentencepiece {
37
38
uint32_t GetRandomGeneratorSeed();
39
int GetNBestTimeout();
40
41
// Sets data dir containing the global resources, e.g., pre-compiled
42
// normalization data.
43
void SetDataDir(absl::string_view data_dir);
44
45
std::string GetDataDir();
46
47
// String utilities
48
namespace string_util {
49
50
template <typename T>
51
23.3k
inline bool DecodePOD(absl::string_view str, T* result) {
52
23.3k
  static_assert(std::is_trivially_copyable_v<T>,
53
23.3k
                "T must be trivially copyable");
54
23.3k
  if (sizeof(*result) != str.size()) {
55
0
    return false;
56
0
  }
57
23.3k
  std::memcpy(result, str.data(), sizeof(T));
58
23.3k
  return true;
59
23.3k
}
60
61
template <typename T>
62
0
inline std::string EncodePOD(const T& value) {
63
0
  static_assert(std::is_trivially_copyable_v<T>,
64
0
                "T must be trivially copyable");
65
0
  return {reinterpret_cast<const char*>(&value), sizeof(T)};
66
0
}
67
68
// Return length of a single UTF-8 source character
69
187M
inline size_t OneCharLen(const char* src) {
70
187M
  return "\1\1\1\1\1\1\1\1\1\1\1\1\2\2\3\4"[(*src & 0xFF) >> 4];
71
187M
}
72
73
// Return (x & 0xC0) == 0x80;
74
// Since trail bytes are always in [0x80, 0xBF], we can optimize:
75
1.94G
inline bool IsTrailByte(char x) { return static_cast<signed char>(x) < -0x40; }
76
77
// Return the character length of a UTF-8 string without heap allocation.
78
5.86M
inline size_t UTF8Len(absl::string_view str) {
79
5.86M
  size_t len = 0;
80
1.88G
  for (char c : str) {
81
1.88G
    if (!IsTrailByte(c)) ++len;
82
1.88G
  }
83
5.86M
  return len;
84
5.86M
}
85
86
73.2M
inline bool IsValidCodepoint(char32_t c) {
87
73.2M
  return (static_cast<uint32_t>(c) < 0xD800) || (c >= 0xE000 && c <= 0x10FFFF);
88
73.2M
}
89
90
bool IsStructurallyValid(absl::string_view str);
91
92
using UnicodeText = std::vector<char32_t>;
93
94
char32_t DecodeUTF8(const char* begin, const char* end, size_t* mblen);
95
96
10.3M
inline char32_t DecodeUTF8(absl::string_view input, size_t* mblen) {
97
10.3M
  return DecodeUTF8(input.data(), input.data() + input.size(), mblen);
98
10.3M
}
99
100
10.3M
inline bool IsValidDecodeUTF8(absl::string_view input, size_t* mblen) {
101
10.3M
  const char32_t c = DecodeUTF8(input, mblen);
102
10.3M
  return c != kUnicodeError || *mblen == 3;
103
10.3M
}
104
105
size_t EncodeUTF8(char32_t c, char* output);
106
107
std::string UnicodeCharToUTF8(char32_t c);
108
109
UnicodeText UTF8ToUnicodeText(absl::string_view utf8);
110
111
std::string UnicodeTextToUTF8(const UnicodeText& utext);
112
113
struct UnicodeTextAndOffsets {
114
  UnicodeText unicode_text;
115
  std::vector<uint32_t> offsets;
116
};
117
118
// - unicode_text is the UTF-8 string converted to UnicodeText.
119
// - offsets.size() == unicode_text.size() + 1
120
// - offsets[0] is always 0.
121
// - offsets[i] is the offset of unicode_text[i] in the original UTF-8 string.
122
UnicodeTextAndOffsets UTF8ToUnicodeTextAndOffsets(absl::string_view utf8);
123
124
}  // namespace string_util
125
126
namespace random {
127
128
absl::BitGen* GetRandomGenerator();
129
130
template <typename T>
131
class ReservoirSampler {
132
 public:
133
  explicit ReservoirSampler(std::vector<T>* sampled, uint64_t size)
134
      : sampled_(sampled), size_(size) {}
135
  explicit ReservoirSampler(std::vector<T>* sampled, uint64_t size,
136
                            uint64_t seed)
137
2.05k
      : sampled_(sampled), size_(size), gen_(std::seed_seq{seed}) {}
138
2.05k
  virtual ~ReservoirSampler() = default;
139
140
18.0k
  void Add(const T& item) {
141
18.0k
    if (size_ == 0) {
142
0
      return;
143
0
    }
144
145
18.0k
    ++total_;
146
18.0k
    if (sampled_->size() < size_) {
147
18.0k
      sampled_->push_back(item);
148
18.0k
    } else {
149
0
      const auto n = absl::Uniform<uint64_t>(gen_, 0, total_ - 1);
150
0
      if (n < sampled_->size()) {
151
0
        (*sampled_)[n] = item;
152
0
      }
153
0
    }
154
18.0k
  }
155
156
38.1k
  [[nodiscard]] uint64_t total_size() const { return total_; }
157
158
 private:
159
  std::vector<T>* sampled_ = nullptr;
160
  uint64_t size_ = 0;
161
  uint64_t total_ = 0;
162
  absl::BitGen gen_;
163
};
164
165
}  // namespace random
166
167
namespace util {
168
169
std::vector<std::string> StrSplitAsCSV(absl::string_view text);
170
171
}  // namespace util
172
173
namespace log_domain {
174
175
double LogSum(const std::vector<double>& xs);
176
177
}  // namespace log_domain
178
}  // namespace sentencepiece
179
#endif  // UTIL_H_