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