/src/icu/icu4c/source/common/bytesinkutil.h
Line | Count | Source (jump to first uncovered line) |
1 | | // © 2017 and later: Unicode, Inc. and others. |
2 | | // License & terms of use: http://www.unicode.org/copyright.html |
3 | | |
4 | | // bytesinkutil.h |
5 | | // created: 2017sep14 Markus W. Scherer |
6 | | |
7 | | #ifndef BYTESINKUTIL_H |
8 | | #define BYTESINKUTIL_H |
9 | | |
10 | | #include <type_traits> |
11 | | |
12 | | #include "unicode/utypes.h" |
13 | | #include "unicode/bytestream.h" |
14 | | #include "unicode/edits.h" |
15 | | #include "charstr.h" |
16 | | #include "cmemory.h" |
17 | | #include "uassert.h" |
18 | | #include "ustr_imp.h" |
19 | | |
20 | | U_NAMESPACE_BEGIN |
21 | | |
22 | | class ByteSink; |
23 | | class Edits; |
24 | | |
25 | | class U_COMMON_API CharStringByteSink : public ByteSink { |
26 | | public: |
27 | | CharStringByteSink(CharString* dest); |
28 | | ~CharStringByteSink() override; |
29 | | |
30 | | CharStringByteSink() = delete; |
31 | | CharStringByteSink(const CharStringByteSink&) = delete; |
32 | | CharStringByteSink& operator=(const CharStringByteSink&) = delete; |
33 | | |
34 | | void Append(const char* bytes, int32_t n) override; |
35 | | |
36 | | char* GetAppendBuffer(int32_t min_capacity, |
37 | | int32_t desired_capacity_hint, |
38 | | char* scratch, |
39 | | int32_t scratch_capacity, |
40 | | int32_t* result_capacity) override; |
41 | | |
42 | | private: |
43 | | CharString& dest_; |
44 | | }; |
45 | | |
46 | | // CharString doesn't provide the public API that StringByteSink requires a |
47 | | // string class to have so this template specialization replaces the default |
48 | | // implementation of StringByteSink<CharString> with CharStringByteSink. |
49 | | template<> |
50 | | class StringByteSink<CharString> : public CharStringByteSink { |
51 | | public: |
52 | 0 | StringByteSink(CharString* dest) : CharStringByteSink(dest) { } |
53 | 0 | StringByteSink(CharString* dest, int32_t /*initialAppendCapacity*/) : CharStringByteSink(dest) { } |
54 | | }; |
55 | | |
56 | | class U_COMMON_API ByteSinkUtil { |
57 | | public: |
58 | | ByteSinkUtil() = delete; // all static |
59 | | |
60 | | /** (length) bytes were mapped to valid (s16, s16Length). */ |
61 | | static UBool appendChange(int32_t length, |
62 | | const char16_t *s16, int32_t s16Length, |
63 | | ByteSink &sink, Edits *edits, UErrorCode &errorCode); |
64 | | |
65 | | /** The bytes at [s, limit[ were mapped to valid (s16, s16Length). */ |
66 | | static UBool appendChange(const uint8_t *s, const uint8_t *limit, |
67 | | const char16_t *s16, int32_t s16Length, |
68 | | ByteSink &sink, Edits *edits, UErrorCode &errorCode); |
69 | | |
70 | | /** (length) bytes were mapped/changed to valid code point c. */ |
71 | | static void appendCodePoint(int32_t length, UChar32 c, ByteSink &sink, Edits *edits = nullptr); |
72 | | |
73 | | /** The few bytes at [src, nextSrc[ were mapped/changed to valid code point c. */ |
74 | | static inline void appendCodePoint(const uint8_t *src, const uint8_t *nextSrc, UChar32 c, |
75 | 0 | ByteSink &sink, Edits *edits = nullptr) { |
76 | 0 | appendCodePoint(static_cast<int32_t>(nextSrc - src), c, sink, edits); |
77 | 0 | } |
78 | | |
79 | | /** Append the two-byte character (U+0080..U+07FF). */ |
80 | | static void appendTwoBytes(UChar32 c, ByteSink &sink); |
81 | | |
82 | | static UBool appendUnchanged(const uint8_t *s, int32_t length, |
83 | | ByteSink &sink, uint32_t options, Edits *edits, |
84 | 0 | UErrorCode &errorCode) { |
85 | 0 | if (U_FAILURE(errorCode)) { return false; } |
86 | 0 | if (length > 0) { appendNonEmptyUnchanged(s, length, sink, options, edits); } |
87 | 0 | return true; |
88 | 0 | } |
89 | | |
90 | | static UBool appendUnchanged(const uint8_t *s, const uint8_t *limit, |
91 | | ByteSink &sink, uint32_t options, Edits *edits, |
92 | | UErrorCode &errorCode); |
93 | | |
94 | | /** |
95 | | * Calls a lambda that writes to a ByteSink with a CheckedArrayByteSink |
96 | | * and then returns through u_terminateChars(), in order to implement |
97 | | * the classic ICU4C C API writing to a fix sized buffer on top of a |
98 | | * contemporary C++ API. |
99 | | * |
100 | | * @param buffer receiving buffer |
101 | | * @param capacity capacity of receiving buffer |
102 | | * @param lambda that gets called with the sink as an argument |
103 | | * @param status set to U_BUFFER_OVERFLOW_ERROR on overflow |
104 | | * @return number of bytes written, or needed (in case of overflow) |
105 | | * @internal |
106 | | */ |
107 | | template <typename F, |
108 | | typename = std::enable_if_t< |
109 | | std::is_invocable_r_v<void, F, ByteSink&, UErrorCode&>>> |
110 | | static int32_t viaByteSinkToTerminatedChars(char* buffer, int32_t capacity, |
111 | | F&& lambda, |
112 | 1.30k | UErrorCode& status) { |
113 | 1.30k | if (U_FAILURE(status)) { return 0; } |
114 | 1.30k | CheckedArrayByteSink sink(buffer, capacity); |
115 | 1.30k | lambda(sink, status); |
116 | 1.30k | if (U_FAILURE(status)) { return 0; } |
117 | | |
118 | 1.30k | int32_t reslen = sink.NumberOfBytesAppended(); |
119 | | |
120 | 1.30k | if (sink.Overflowed()) { |
121 | 0 | status = U_BUFFER_OVERFLOW_ERROR; |
122 | 0 | return reslen; |
123 | 0 | } |
124 | | |
125 | 1.30k | return u_terminateChars(buffer, capacity, reslen, &status); |
126 | 1.30k | } locid.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<icu_78::Locale::init(icu_78::StringPiece, signed char)::$_0::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char*, int, UErrorCode&) const::{lambda(icu_78::ByteSink&, UErrorCode&)#1}, void>(char*, int, icu_78::Locale::init(icu_78::StringPiece, signed char)::$_0::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char*, int, UErrorCode&) const::{lambda(icu_78::ByteSink&, UErrorCode&)#1}&&, UErrorCode&) Line | Count | Source | 112 | 886 | UErrorCode& status) { | 113 | 886 | if (U_FAILURE(status)) { return 0; } | 114 | 886 | CheckedArrayByteSink sink(buffer, capacity); | 115 | 886 | lambda(sink, status); | 116 | 886 | if (U_FAILURE(status)) { return 0; } | 117 | | | 118 | 886 | int32_t reslen = sink.NumberOfBytesAppended(); | 119 | | | 120 | 886 | if (sink.Overflowed()) { | 121 | 0 | status = U_BUFFER_OVERFLOW_ERROR; | 122 | 0 | return reslen; | 123 | 0 | } | 124 | | | 125 | 886 | return u_terminateChars(buffer, capacity, reslen, &status); | 126 | 886 | } |
Unexecuted instantiation: loclikely.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_addLikelySubtags_78::$_0, void>(char*, int, uloc_addLikelySubtags_78::$_0&&, UErrorCode&) Unexecuted instantiation: loclikely.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_minimizeSubtags_78::$_0, void>(char*, int, uloc_minimizeSubtags_78::$_0&&, UErrorCode&) uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getKeywordValue_78::$_0, void>(char*, int, uloc_getKeywordValue_78::$_0&&, UErrorCode&) Line | Count | Source | 112 | 420 | UErrorCode& status) { | 113 | 420 | if (U_FAILURE(status)) { return 0; } | 114 | 420 | CheckedArrayByteSink sink(buffer, capacity); | 115 | 420 | lambda(sink, status); | 116 | 420 | if (U_FAILURE(status)) { return 0; } | 117 | | | 118 | 420 | int32_t reslen = sink.NumberOfBytesAppended(); | 119 | | | 120 | 420 | if (sink.Overflowed()) { | 121 | 0 | status = U_BUFFER_OVERFLOW_ERROR; | 122 | 0 | return reslen; | 123 | 0 | } | 124 | | | 125 | 420 | return u_terminateChars(buffer, capacity, reslen, &status); | 126 | 420 | } |
Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getParent_78::$_0, void>(char*, int, uloc_getParent_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getLanguage_78::$_0, void>(char*, int, uloc_getLanguage_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getScript_78::$_0, void>(char*, int, uloc_getScript_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getCountry_78::$_0, void>(char*, int, uloc_getCountry_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getVariant_78::$_0, void>(char*, int, uloc_getVariant_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getName_78::$_0, void>(char*, int, uloc_getName_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_getBaseName_78::$_0, void>(char*, int, uloc_getBaseName_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_canonicalize_78::$_0, void>(char*, int, uloc_canonicalize_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc_tag.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_toLanguageTag_78::$_0, void>(char*, int, uloc_toLanguageTag_78::$_0&&, UErrorCode&) Unexecuted instantiation: uloc_tag.cpp:int icu_78::ByteSinkUtil::viaByteSinkToTerminatedChars<uloc_forLanguageTag_78::$_0, void>(char*, int, uloc_forLanguageTag_78::$_0&&, UErrorCode&) |
127 | | |
128 | | /** |
129 | | * Calls a lambda that writes to a ByteSink with a CharStringByteSink and |
130 | | * then returns a CharString, in order to implement a contemporary C++ API |
131 | | * on top of a C/C++ compatibility ByteSink API. |
132 | | * |
133 | | * @param lambda that gets called with the sink as an argument |
134 | | * @param status to check and report |
135 | | * @return the resulting string, or an empty string (in case of error) |
136 | | * @internal |
137 | | */ |
138 | | template <typename F, |
139 | | typename = std::enable_if_t< |
140 | | std::is_invocable_r_v<void, F, ByteSink&, UErrorCode&>>> |
141 | 1.54k | static CharString viaByteSinkToCharString(F&& lambda, UErrorCode& status) { |
142 | 1.54k | if (U_FAILURE(status)) { return {}; } |
143 | 1.54k | CharString result; |
144 | 1.54k | CharStringByteSink sink(&result); |
145 | 1.54k | lambda(sink, status); |
146 | 1.54k | return result; |
147 | 1.54k | } Unexecuted instantiation: loclikely.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_addLikelySubtags_78(char const*, UErrorCode&)::$_0, void>(ulocimp_addLikelySubtags_78(char const*, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: loclikely.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_minimizeSubtags_78(char const*, bool, UErrorCode&)::$_0, void>(ulocimp_minimizeSubtags_78(char const*, bool, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getKeywords_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char, bool, UErrorCode&)::$_0, void>(ulocimp_getKeywords_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char, bool, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getKeywordValue_78(char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getKeywordValue_78(char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getLanguage_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getLanguage_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getScript_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getScript_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getRegion_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getRegion_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getVariant_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getVariant_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getParent_78(char const*, UErrorCode&)::$_0, void>(ulocimp_getParent_78(char const*, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getName_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getName_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_getBaseName_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_getBaseName_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Line | Count | Source | 141 | 1.54k | static CharString viaByteSinkToCharString(F&& lambda, UErrorCode& status) { | 142 | 1.54k | if (U_FAILURE(status)) { return {}; } | 143 | 1.54k | CharString result; | 144 | 1.54k | CharStringByteSink sink(&result); | 145 | 1.54k | lambda(sink, status); | 146 | 1.54k | return result; | 147 | 1.54k | } |
uloc.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_canonicalize_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0, void>(ulocimp_canonicalize_78(std::__1::basic_string_view<char, std::__1::char_traits<char> >, UErrorCode&)::$_0&&, UErrorCode&) Line | Count | Source | 141 | 1 | static CharString viaByteSinkToCharString(F&& lambda, UErrorCode& status) { | 142 | 1 | if (U_FAILURE(status)) { return {}; } | 143 | 1 | CharString result; | 144 | 1 | CharStringByteSink sink(&result); | 145 | 1 | lambda(sink, status); | 146 | 1 | return result; | 147 | 1 | } |
Unexecuted instantiation: uloc_tag.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_toLanguageTag_78(char const*, bool, UErrorCode&)::$_0, void>(ulocimp_toLanguageTag_78(char const*, bool, UErrorCode&)::$_0&&, UErrorCode&) Unexecuted instantiation: uloc_tag.cpp:icu_78::CharString icu_78::ByteSinkUtil::viaByteSinkToCharString<ulocimp_forLanguageTag_78(char const*, int, int*, UErrorCode&)::$_0, void>(ulocimp_forLanguageTag_78(char const*, int, int*, UErrorCode&)::$_0&&, UErrorCode&) |
148 | | |
149 | | private: |
150 | | static void appendNonEmptyUnchanged(const uint8_t *s, int32_t length, |
151 | | ByteSink &sink, uint32_t options, Edits *edits); |
152 | | }; |
153 | | |
154 | | U_NAMESPACE_END |
155 | | |
156 | | #endif //BYTESINKUTIL_H |