1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/i18n/char_iterator.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string_view>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/third_party/icu/icu_utf.h"
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker namespace base {
13*6777b538SAndroid Build Coastguard Worker namespace i18n {
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker // UTF8CharIterator ------------------------------------------------------------
16*6777b538SAndroid Build Coastguard Worker
UTF8CharIterator(std::string_view str)17*6777b538SAndroid Build Coastguard Worker UTF8CharIterator::UTF8CharIterator(std::string_view str)
18*6777b538SAndroid Build Coastguard Worker : str_(str), array_pos_(0), next_pos_(0), char_pos_(0), char_(0) {
19*6777b538SAndroid Build Coastguard Worker if (!str_.empty())
20*6777b538SAndroid Build Coastguard Worker CBU8_NEXT(str_.data(), next_pos_, str_.length(), char_);
21*6777b538SAndroid Build Coastguard Worker }
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker UTF8CharIterator::~UTF8CharIterator() = default;
24*6777b538SAndroid Build Coastguard Worker
Advance()25*6777b538SAndroid Build Coastguard Worker bool UTF8CharIterator::Advance() {
26*6777b538SAndroid Build Coastguard Worker if (array_pos_ >= str_.length())
27*6777b538SAndroid Build Coastguard Worker return false;
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker array_pos_ = next_pos_;
30*6777b538SAndroid Build Coastguard Worker char_pos_++;
31*6777b538SAndroid Build Coastguard Worker if (next_pos_ < str_.length())
32*6777b538SAndroid Build Coastguard Worker CBU8_NEXT(str_.data(), next_pos_, str_.length(), char_);
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker return true;
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker // UTF16CharIterator -----------------------------------------------------------
38*6777b538SAndroid Build Coastguard Worker
UTF16CharIterator(std::u16string_view str)39*6777b538SAndroid Build Coastguard Worker UTF16CharIterator::UTF16CharIterator(std::u16string_view str)
40*6777b538SAndroid Build Coastguard Worker : UTF16CharIterator(str, 0) {}
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker UTF16CharIterator::UTF16CharIterator(UTF16CharIterator&& to_move) = default;
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker UTF16CharIterator::~UTF16CharIterator() = default;
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker UTF16CharIterator& UTF16CharIterator::operator=(UTF16CharIterator&& to_move) =
47*6777b538SAndroid Build Coastguard Worker default;
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker // static
LowerBound(std::u16string_view str,size_t array_index)50*6777b538SAndroid Build Coastguard Worker UTF16CharIterator UTF16CharIterator::LowerBound(std::u16string_view str,
51*6777b538SAndroid Build Coastguard Worker size_t array_index) {
52*6777b538SAndroid Build Coastguard Worker DCHECK_LE(array_index, str.length());
53*6777b538SAndroid Build Coastguard Worker CBU16_SET_CP_START(str.data(), 0, array_index);
54*6777b538SAndroid Build Coastguard Worker return UTF16CharIterator(str, array_index);
55*6777b538SAndroid Build Coastguard Worker }
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker // static
UpperBound(std::u16string_view str,size_t array_index)58*6777b538SAndroid Build Coastguard Worker UTF16CharIterator UTF16CharIterator::UpperBound(std::u16string_view str,
59*6777b538SAndroid Build Coastguard Worker size_t array_index) {
60*6777b538SAndroid Build Coastguard Worker DCHECK_LE(array_index, str.length());
61*6777b538SAndroid Build Coastguard Worker CBU16_SET_CP_LIMIT(str.data(), 0, array_index, str.length());
62*6777b538SAndroid Build Coastguard Worker return UTF16CharIterator(str, array_index);
63*6777b538SAndroid Build Coastguard Worker }
64*6777b538SAndroid Build Coastguard Worker
NextCodePoint() const65*6777b538SAndroid Build Coastguard Worker int32_t UTF16CharIterator::NextCodePoint() const {
66*6777b538SAndroid Build Coastguard Worker if (next_pos_ >= str_.length())
67*6777b538SAndroid Build Coastguard Worker return 0;
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker base_icu::UChar32 c;
70*6777b538SAndroid Build Coastguard Worker CBU16_GET(str_.data(), 0, next_pos_, str_.length(), c);
71*6777b538SAndroid Build Coastguard Worker return c;
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
PreviousCodePoint() const74*6777b538SAndroid Build Coastguard Worker int32_t UTF16CharIterator::PreviousCodePoint() const {
75*6777b538SAndroid Build Coastguard Worker if (array_pos_ == 0)
76*6777b538SAndroid Build Coastguard Worker return 0;
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker uint32_t pos = array_pos_;
79*6777b538SAndroid Build Coastguard Worker base_icu::UChar32 c;
80*6777b538SAndroid Build Coastguard Worker CBU16_PREV(str_.data(), 0, pos, c);
81*6777b538SAndroid Build Coastguard Worker return c;
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
Advance()84*6777b538SAndroid Build Coastguard Worker bool UTF16CharIterator::Advance() {
85*6777b538SAndroid Build Coastguard Worker if (array_pos_ >= str_.length())
86*6777b538SAndroid Build Coastguard Worker return false;
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker array_pos_ = next_pos_;
89*6777b538SAndroid Build Coastguard Worker char_offset_++;
90*6777b538SAndroid Build Coastguard Worker if (next_pos_ < str_.length())
91*6777b538SAndroid Build Coastguard Worker ReadChar();
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker return true;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
Rewind()96*6777b538SAndroid Build Coastguard Worker bool UTF16CharIterator::Rewind() {
97*6777b538SAndroid Build Coastguard Worker if (array_pos_ == 0)
98*6777b538SAndroid Build Coastguard Worker return false;
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker next_pos_ = array_pos_;
101*6777b538SAndroid Build Coastguard Worker char_offset_--;
102*6777b538SAndroid Build Coastguard Worker CBU16_PREV(str_.data(), 0, array_pos_, char_);
103*6777b538SAndroid Build Coastguard Worker return true;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker
UTF16CharIterator(std::u16string_view str,size_t initial_pos)106*6777b538SAndroid Build Coastguard Worker UTF16CharIterator::UTF16CharIterator(std::u16string_view str,
107*6777b538SAndroid Build Coastguard Worker size_t initial_pos)
108*6777b538SAndroid Build Coastguard Worker : str_(str),
109*6777b538SAndroid Build Coastguard Worker array_pos_(initial_pos),
110*6777b538SAndroid Build Coastguard Worker next_pos_(initial_pos),
111*6777b538SAndroid Build Coastguard Worker char_offset_(0),
112*6777b538SAndroid Build Coastguard Worker char_(0) {
113*6777b538SAndroid Build Coastguard Worker // This has the side-effect of advancing |next_pos_|.
114*6777b538SAndroid Build Coastguard Worker if (array_pos_ < str_.length())
115*6777b538SAndroid Build Coastguard Worker ReadChar();
116*6777b538SAndroid Build Coastguard Worker }
117*6777b538SAndroid Build Coastguard Worker
ReadChar()118*6777b538SAndroid Build Coastguard Worker void UTF16CharIterator::ReadChar() {
119*6777b538SAndroid Build Coastguard Worker // This is actually a huge macro, so is worth having in a separate function.
120*6777b538SAndroid Build Coastguard Worker CBU16_NEXT(str_.data(), next_pos_, str_.length(), char_);
121*6777b538SAndroid Build Coastguard Worker }
122*6777b538SAndroid Build Coastguard Worker
123*6777b538SAndroid Build Coastguard Worker } // namespace i18n
124*6777b538SAndroid Build Coastguard Worker } // namespace base
125