@@ -146,6 +146,106 @@ const int8_t unbase64_table[256] =
146146 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1
147147 };
148148
149+ // ============================================================================
150+ // Hex
151+
152+ const int8_t unhex_table[256 ] =
153+ { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
154+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
155+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
156+ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , -1 , -1 , -1 , -1 , -1 , -1 ,
157+ -1 , 10 , 11 , 12 , 13 , 14 , 15 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
158+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
159+ -1 , 10 , 11 , 12 , 13 , 14 , 15 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
160+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
161+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
162+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
163+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
164+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
165+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
166+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
167+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
168+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1
169+ };
170+
171+ size_t HexEncode (
172+ const char * src,
173+ size_t slen,
174+ char * dst,
175+ size_t dlen) {
176+ // We know how much we'll write, just make sure that there's space.
177+ NBYTES_ASSERT_TRUE (
178+ dlen >= MultiplyWithOverflowCheck<size_t >(slen, 2u ) &&
179+ " not enough space provided for hex encode" );
180+
181+ dlen = slen * 2 ;
182+ for (size_t i = 0 , k = 0 ; k < dlen; i += 1 , k += 2 ) {
183+ static const char hex[] = " 0123456789abcdef" ;
184+ uint8_t val = static_cast <uint8_t >(src[i]);
185+ dst[k + 0 ] = hex[val >> 4 ];
186+ dst[k + 1 ] = hex[val & 15 ];
187+ }
188+
189+ return dlen;
190+ }
191+
192+ std::string HexEncode (const char * src, size_t slen) {
193+ size_t dlen = slen * 2 ;
194+ std::string dst (dlen, ' \0 ' );
195+ HexEncode (src, slen, dst.data (), dlen);
196+ return dst;
197+ }
198+
199+ // ============================================================================
200+
201+ void ForceAsciiSlow (const char * src, char * dst, size_t len) {
202+ for (size_t i = 0 ; i < len; ++i) {
203+ dst[i] = src[i] & 0x7f ;
204+ }
205+ }
206+
207+ void ForceAscii (const char * src, char * dst, size_t len) {
208+ if (len < 16 ) {
209+ ForceAsciiSlow (src, dst, len);
210+ return ;
211+ }
212+
213+ const unsigned bytes_per_word = sizeof (uintptr_t );
214+ const unsigned align_mask = bytes_per_word - 1 ;
215+ const unsigned src_unalign = reinterpret_cast <uintptr_t >(src) & align_mask;
216+ const unsigned dst_unalign = reinterpret_cast <uintptr_t >(dst) & align_mask;
217+
218+ if (src_unalign > 0 ) {
219+ if (src_unalign == dst_unalign) {
220+ const unsigned unalign = bytes_per_word - src_unalign;
221+ ForceAsciiSlow (src, dst, unalign);
222+ src += unalign;
223+ dst += unalign;
224+ len -= src_unalign;
225+ } else {
226+ ForceAsciiSlow (src, dst, len);
227+ return ;
228+ }
229+ }
230+
231+ #if defined(_WIN64) || defined(_LP64)
232+ const uintptr_t mask = ~0x8080808080808080ll ;
233+ #else
234+ const uintptr_t mask = ~0x80808080l ;
235+ #endif
149236
237+ const uintptr_t * srcw = reinterpret_cast <const uintptr_t *>(src);
238+ uintptr_t * dstw = reinterpret_cast <uintptr_t *>(dst);
239+
240+ for (size_t i = 0 , n = len / bytes_per_word; i < n; ++i) {
241+ dstw[i] = srcw[i] & mask;
242+ }
243+
244+ const unsigned remainder = len & align_mask;
245+ if (remainder > 0 ) {
246+ const size_t offset = len - remainder;
247+ ForceAsciiSlow (src + offset, dst + offset, remainder);
248+ }
249+ }
150250
151251} // namespace nbytes
0 commit comments