8 #ifndef INCL_evo_impl_strscan_h 9 #define INCL_evo_impl_strscan_h 18 #if !defined(EVO_IMPL_SSE42) && defined(EVO_IMPL_SSE2) 19 #pragma intrinsic(_BitScanForward) 20 #pragma intrinsic(_BitScanReverse) 22 #elif defined(EVO_IMPL_SSE42) 23 #include <nmmintrin.h> 24 #elif defined(EVO_IMPL_SSE2) 25 #include <emmintrin.h> 38 inline const char* str_scan_nws_default(
const char* str,
const char* end) {
39 for (; str < end; ++str)
40 if (!(*str ==
' ' || *str ==
'\t' || *str ==
'\n' || *str ==
'\r'))
46 inline const char* str_scan_nws_default_r(
const char* str,
const char* end) {
49 if (!(*end ==
' ' || *end ==
'\t' || *end ==
'\n' || *end ==
'\r'))
56 inline const char* str_scan_ndelim_default(
const char* str,
const char* end,
char delim1,
char delim2) {
57 for (; str < end; ++str)
58 if (!(*str == delim1 || *str == delim2))
64 inline const char* str_scan_ndelim_default_r(
const char* str,
const char* end,
char delim1,
char delim2) {
67 if (!(*end == delim1 || *end == delim2))
74 inline const char* str_scan_delim_default(
const char* str,
const char* end,
char delim1,
char delim2) {
75 for (; str < end; ++str)
76 if (*str == delim1 || *str == delim2)
82 inline const char* str_scan_delim_default_r(
const char* str,
const char* end,
char delim1,
char delim2) {
85 if (*end == delim1 || *end == delim2)
92 inline const char* str_scan_delim_default(
const char* str,
const char* end,
const char* delims, uint delim_count) {
93 for (; str < end; ++str)
94 if (::memchr(delims, *str, delim_count) != NULL)
100 inline const char* str_scan_delim_default_r(
const char* str,
const char* end,
const char* delims, uint delim_count) {
103 if (::memchr(delims, *end, delim_count) != NULL)
110 static const size_t SSE_BATCH_SIZE = 16;
111 static const size_t SSE_ALIGN16 = 0x0F;
112 static const size_t SSE_ALIGN16_MASK = ~SSE_ALIGN16;
115 #if defined(EVO_IMPL_SSE42) 117 inline const char* str_scan_nws_cpu(
const char* str,
const char* end) {
120 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
121 while (str < align16)
122 if (!(*str ==
' ' || *str ==
'\t' || *str ==
'\n' || *str ==
'\r') || ++str == end)
126 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY;
127 const __m128i ws = _mm_loadu_si128((__m128i*)
" \t\n\r\0\0\0\0\0\0\0\0\0\0\0");
128 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
129 for (; str < align16; str += SSE_BATCH_SIZE) {
130 const int i = _mm_cmpistri(ws, _mm_load_si128((__m128i*)str), FLAGS);
131 if (i != (
int)SSE_BATCH_SIZE)
136 for (; str < end; ++str)
137 if (!(*str ==
' ' || *str ==
'\t' || *str ==
'\n' || *str ==
'\r'))
144 inline const char* str_scan_nws_cpu_r(
const char* str,
const char* end) {
146 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
149 while (end > align16) {
151 if (!(*end ==
' ' || *end ==
'\t' || *end ==
'\n' || *end ==
'\r'))
156 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_MOST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY;
157 const __m128i ws = _mm_loadu_si128((__m128i*)
" \t\n\r\0\0\0\0\0\0\0\0\0\0\0");
158 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
159 while (end > align16) {
160 end -= SSE_BATCH_SIZE;
161 const int i = _mm_cmpistri(ws, _mm_load_si128((__m128i*)end), FLAGS);
162 if (i != (
int)SSE_BATCH_SIZE)
170 if (!(*end ==
' ' || *end ==
'\t' || *end ==
'\n' || *end ==
'\r'))
180 inline const char* str_scan_ndelim_cpu(
const char* str,
const char* end,
char delim1,
char delim2) {
183 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
184 while (str < align16)
185 if (!(*str == delim1 || *str == delim2) || ++str == end)
189 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
193 char buf[SSE_BATCH_SIZE];
195 ::memset(buf + 1, delim2, SSE_BATCH_SIZE - 1);
196 delims_in = _mm_loadu_si128((__m128i*)buf);
199 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY;
201 const int i = _mm_cmpistri(delims_in, _mm_load_si128((__m128i*)str), FLAGS);
202 if (i != (
int)SSE_BATCH_SIZE)
204 str += SSE_BATCH_SIZE;
205 }
while (str < align16);
209 for (; str < end; ++str)
210 if (!(*str == delim1 || *str == delim2))
217 inline const char* str_scan_ndelim_cpu_r(
const char* str,
const char* end,
char delim1,
char delim2) {
219 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
222 while (end > align16) {
224 if (!(*end == delim1 || *end == delim2))
229 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
233 char buf[SSE_BATCH_SIZE];
235 ::memset(buf + 1, delim2, SSE_BATCH_SIZE - 1);
236 delims_in = _mm_loadu_si128((__m128i*)buf);
239 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_MOST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY;
241 end -= SSE_BATCH_SIZE;
242 const int i = _mm_cmpistri(delims_in, _mm_load_si128((__m128i*)end), FLAGS);
243 if (i != (
int)SSE_BATCH_SIZE)
245 }
while (end > align16);
252 if (!(*end == delim1 || *end == delim2))
262 inline const char* str_scan_delim_cpu(
const char* str,
const char* end,
char delim1,
char delim2) {
265 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
266 while (str < align16)
267 if (*str == delim1 || *str == delim2 || ++str == end)
271 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
275 char buf[SSE_BATCH_SIZE];
277 ::memset(buf + 1, delim2, SSE_BATCH_SIZE - 1);
278 delims_in = _mm_loadu_si128((__m128i*)buf);
281 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT;
283 const int i = _mm_cmpistri(delims_in, _mm_load_si128((__m128i*)str), FLAGS);
284 if (i != (
int)SSE_BATCH_SIZE)
286 str += SSE_BATCH_SIZE;
287 }
while (str < align16);
291 for (; str < end; ++str)
292 if (*str == delim1 || *str == delim2)
299 inline const char* str_scan_delim_cpu_r(
const char* str,
const char* end,
char delim1,
char delim2) {
301 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
304 while (end > align16) {
306 if (*end == delim1 || *end == delim2)
311 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
315 char buf[SSE_BATCH_SIZE];
317 ::memset(buf + 1, delim2, SSE_BATCH_SIZE - 1);
318 delims_in = _mm_loadu_si128((__m128i*)buf);
321 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_MOST_SIGNIFICANT;
323 end -= SSE_BATCH_SIZE;
324 const int i = _mm_cmpistri(delims_in, _mm_load_si128((__m128i*)end), FLAGS);
325 if (i != (
int)SSE_BATCH_SIZE)
327 }
while (end > align16);
334 if (*end == delim1 || *end == delim2)
342 inline const char* str_scan_delim_cpu(
const char* str,
const char* end,
const char* delims, uint delim_count) {
343 assert( delim_count > 1 );
344 assert( delim_count <= SSE_BATCH_SIZE );
347 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
348 while (str < align16)
349 if (::memchr(delims, *str, delim_count) != NULL || ++str == end)
353 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
357 char buf[SSE_BATCH_SIZE];
358 ::memcpy(buf, delims, delim_count);
359 if (delim_count < SSE_BATCH_SIZE)
360 ::memset(buf + delim_count, delims[0], SSE_BATCH_SIZE - delim_count);
361 delims_in = _mm_loadu_si128((__m128i*)buf);
364 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT;
366 const int i = _mm_cmpistri(delims_in, _mm_load_si128((__m128i*)str), FLAGS);
367 if (i != (
int)SSE_BATCH_SIZE)
369 str += SSE_BATCH_SIZE;
370 }
while (str < align16);
374 for (; str < end; ++str)
375 if (::memchr(delims, *str, delim_count) != NULL)
382 inline const char* str_scan_delim_cpu_r(
const char* str,
const char* end,
const char* delims, uint delim_count) {
384 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
387 while (end > align16) {
389 if (::memchr(delims, *end, delim_count) != NULL)
394 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
398 char buf[SSE_BATCH_SIZE];
399 ::memcpy(buf, delims, delim_count);
400 if (delim_count < SSE_BATCH_SIZE)
401 ::memset(buf + delim_count, delims[0], SSE_BATCH_SIZE - delim_count);
402 delims_in = _mm_loadu_si128((__m128i*)buf);
405 const int FLAGS = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_MOST_SIGNIFICANT;
407 end -= SSE_BATCH_SIZE;
408 const int i = _mm_cmpistri(delims_in, _mm_load_si128((__m128i*)end), FLAGS);
409 if (i != (
int)SSE_BATCH_SIZE)
411 }
while (end > align16);
418 if (::memchr(delims, *end, delim_count) != NULL)
425 #elif defined(EVO_IMPL_SSE2) 427 inline const char* str_scan_nws_cpu(
const char* str,
const char* end) {
428 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
431 while (str < align16) {
432 if (!(*str ==
' ' || *str ==
'\t' || *str ==
'\n' || *str ==
'\r'))
438 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
441 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" 442 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" 443 "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r";
444 const __m128i ws1 = _mm_loadu_si128((__m128i*)WS);
445 const __m128i ws2 = _mm_loadu_si128((__m128i*)(WS + SSE_BATCH_SIZE));
446 const __m128i ws3 = _mm_loadu_si128((__m128i*)(WS + (SSE_BATCH_SIZE * 2)));
447 const __m128i ws4 = _mm_loadu_si128((__m128i*)(WS + (SSE_BATCH_SIZE * 3)));
452 n = _mm_load_si128((__m128i*)str);
455 v = _mm_or_si128(_mm_cmpeq_epi8(n, ws1), _mm_cmpeq_epi8(n, ws2));
456 v = _mm_or_si128(v, _mm_cmpeq_epi8(n, ws3));
457 v = _mm_or_si128(v, _mm_cmpeq_epi8(n, ws4));
460 r = (uint16)~_mm_movemask_epi8(v);
462 #if defined(_MSC_VER) 464 _BitScanForward(&i, r);
467 return str + __builtin_ffs(r) - 1;
470 str += SSE_BATCH_SIZE;
471 }
while (str < align16);
476 for (; str < end; ++str)
477 if (!(*str ==
' ' || *str ==
'\t' || *str ==
'\n' || *str ==
'\r'))
483 inline const char* str_scan_nws_cpu_r(
const char* str,
const char* end) {
484 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
487 while (end > align16) {
489 if (!(*end ==
' ' || *end ==
'\t' || *end ==
'\n' || *end ==
'\r'))
494 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
497 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" 498 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" 499 "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r";
500 const __m128i ws1 = _mm_loadu_si128((__m128i*)WS);
501 const __m128i ws2 = _mm_loadu_si128((__m128i*)(WS + SSE_BATCH_SIZE));
502 const __m128i ws3 = _mm_loadu_si128((__m128i*)(WS + (SSE_BATCH_SIZE * 2)));
503 const __m128i ws4 = _mm_loadu_si128((__m128i*)(WS + (SSE_BATCH_SIZE * 3)));
508 end -= SSE_BATCH_SIZE;
509 n = _mm_load_si128((__m128i*)end);
512 v = _mm_or_si128(_mm_cmpeq_epi8(n, ws1), _mm_cmpeq_epi8(n, ws2));
513 v = _mm_or_si128(v, _mm_cmpeq_epi8(n, ws3));
514 v = _mm_or_si128(v, _mm_cmpeq_epi8(n, ws4));
517 r = (uint16)~_mm_movemask_epi8(v);
519 #if defined(_MSC_VER) 521 _BitScanReverse(&i, r);
527 }
while (end > align16);
534 if (!(*end ==
' ' || *end ==
'\t' || *end ==
'\n' || *end ==
'\r'))
543 inline const char* str_scan_ndelim_cpu(
const char* str,
const char* end,
char delim1,
char delim2) {
544 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
547 while (str < align16)
548 if (!(*str == delim1 || *str == delim2) || ++str == end)
552 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
554 __m128i delim_in1, delim_in2;
556 char buf[SSE_BATCH_SIZE];
557 ::memset(buf, delim1, SSE_BATCH_SIZE);
558 delim_in1 = _mm_loadu_si128((__m128i*)buf);
560 ::memset(buf, delim2, SSE_BATCH_SIZE);
561 delim_in2 = _mm_loadu_si128((__m128i*)buf);
568 n = _mm_load_si128((__m128i*)str);
569 r = (uint16)~_mm_movemask_epi8( _mm_or_si128(_mm_cmpeq_epi8(n, delim_in1), _mm_cmpeq_epi8(n, delim_in2)) );
571 #if defined(_MSC_VER) 573 _BitScanForward(&i, r);
576 return str + __builtin_ffs(r) - 1;
579 str += SSE_BATCH_SIZE;
580 }
while(str < align16);
585 for (; str < end; ++str)
586 if (!(*str == delim1 || *str == delim2))
592 inline const char* str_scan_ndelim_cpu_r(
const char* str,
const char* end,
char delim1,
char delim2) {
593 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
596 while (end > align16) {
598 if (!(*end == delim1 || *end == delim2))
603 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
605 __m128i delim_in1, delim_in2;
607 char buf[SSE_BATCH_SIZE];
608 ::memset(buf, delim1, SSE_BATCH_SIZE);
609 delim_in1 = _mm_loadu_si128((__m128i*)buf);
611 ::memset(buf, delim2, SSE_BATCH_SIZE);
612 delim_in2 = _mm_loadu_si128((__m128i*)buf);
619 end -= SSE_BATCH_SIZE;
620 n = _mm_load_si128((__m128i*)end);
621 r = (uint16)~_mm_movemask_epi8( _mm_or_si128(_mm_cmpeq_epi8(n, delim_in1), _mm_cmpeq_epi8(n, delim_in2)) );
623 #if defined(_MSC_VER) 625 _BitScanReverse(&i, r);
631 }
while (end > align16);
638 if (!(*end == delim1 || *end == delim2))
647 inline const char* str_scan_delim_cpu(
const char* str,
const char* end,
char delim1,
char delim2) {
648 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
651 while (str < align16)
652 if (*str == delim1 || *str == delim2 || ++str == end)
656 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
658 __m128i delim_in1, delim_in2;
660 char buf[SSE_BATCH_SIZE];
661 ::memset(buf, delim1, SSE_BATCH_SIZE);
662 delim_in1 = _mm_loadu_si128((__m128i*)buf);
664 ::memset(buf, delim2, SSE_BATCH_SIZE);
665 delim_in2 = _mm_loadu_si128((__m128i*)buf);
672 n = _mm_load_si128((__m128i*)str);
673 r = (uint16)_mm_movemask_epi8( _mm_or_si128(_mm_cmpeq_epi8(n, delim_in1), _mm_cmpeq_epi8(n, delim_in2)) );
675 #if defined(_MSC_VER) 677 _BitScanForward(&i, r);
680 return str + __builtin_ffs(r) - 1;
683 str += SSE_BATCH_SIZE;
684 }
while (str < align16);
689 for (; str < end; ++str)
690 if (*str == delim1 || *str == delim2)
696 inline const char* str_scan_delim_cpu(
const char* str,
const char* end,
const char* delims, uint delim_count) {
697 assert( delim_count > 1 );
698 assert( delim_count <= SSE_BATCH_SIZE );
699 const char* align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
702 while (str < align16)
703 if (::memchr(delims, *str, delim_count) != NULL || ++str == end)
707 align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
710 __m128i delims_in[SSE_BATCH_SIZE];
712 char buf[SSE_BATCH_SIZE];
713 for (i = 0; i < delim_count; ++i) {
714 ::memset(buf, delims[i], SSE_BATCH_SIZE);
715 delims_in[i] = _mm_loadu_si128((__m128i*)buf);
722 n = _mm_load_si128((__m128i*)str);
725 v = _mm_or_si128(_mm_cmpeq_epi8(n, delims_in[0]), _mm_cmpeq_epi8(n, delims_in[1]));
726 for (i = 2; i < delim_count; ++i)
727 v = _mm_or_si128(v, _mm_cmpeq_epi8(n, delims_in[i]));
730 r = (uint16)_mm_movemask_epi8(v);
732 #if defined(_MSC_VER) 734 _BitScanForward(&j, r);
737 return str + __builtin_ffs(r) - 1;
740 str += SSE_BATCH_SIZE;
741 }
while (str < align16);
746 for (; str < end; ++str)
747 if (::memchr(delims, *str, delim_count) != NULL)
753 inline const char* str_scan_delim_cpu_r(
const char* str,
const char* end,
char delim1,
char delim2) {
754 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
757 while (end > align16) {
759 if (*end == delim1 || *end == delim2)
764 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
766 __m128i delim_in1, delim_in2;
768 char buf[SSE_BATCH_SIZE];
769 ::memset(buf, delim1, SSE_BATCH_SIZE);
770 delim_in1 = _mm_loadu_si128((__m128i*)buf);
772 ::memset(buf, delim2, SSE_BATCH_SIZE);
773 delim_in2 = _mm_loadu_si128((__m128i*)buf);
780 end -= SSE_BATCH_SIZE;
781 n = _mm_load_si128((__m128i*)end);
782 r = (uint16)_mm_movemask_epi8( _mm_or_si128(_mm_cmpeq_epi8(n, delim_in1), _mm_cmpeq_epi8(n, delim_in2)) );
784 #if defined(_MSC_VER) 786 _BitScanReverse(&i, r);
792 }
while (end > align16);
799 if (*end == delim1 || *end == delim2)
806 inline const char* str_scan_delim_cpu_r(
const char* str,
const char* end,
const char* delims, uint delim_count) {
807 const char* align16 = (
char*)((
size_t)end & SSE_ALIGN16_MASK);
810 while (end > align16) {
812 if (::memchr(delims, *end, delim_count) != NULL)
817 align16 = (
char*)( ((
size_t)str + SSE_ALIGN16) & SSE_ALIGN16_MASK );
820 __m128i delims_in[SSE_BATCH_SIZE];
822 char buf[SSE_BATCH_SIZE];
823 for (i = 0; i < delim_count; ++i) {
824 ::memset(buf, delims[i], SSE_BATCH_SIZE);
825 delims_in[i] = _mm_loadu_si128((__m128i*)buf);
832 end -= SSE_BATCH_SIZE;
833 n = _mm_load_si128((__m128i*)end);
836 v = _mm_or_si128(_mm_cmpeq_epi8(n, delims_in[0]), _mm_cmpeq_epi8(n, delims_in[1]));
837 for (i = 2; i < delim_count; ++i)
838 v = _mm_or_si128(v, _mm_cmpeq_epi8(n, delims_in[i]));
841 r = (uint16)_mm_movemask_epi8(v);
843 #if defined(_MSC_VER) 845 _BitScanReverse(&j, r);
851 }
while (end > align16);
858 if (::memchr(delims, *end, delim_count) != NULL)
878 assert( str != NULL );
879 assert( str <= end );
881 return impl::str_scan_nws_cpu(str, end);
883 return impl::str_scan_nws_default(str, end);
897 assert( str != NULL );
898 assert( str <= end );
900 return impl::str_scan_nws_cpu_r(str, end);
902 return impl::str_scan_nws_default_r(str, end);
916 inline const char*
str_scan_nws(
const char* str,
const char* end,
char delim) {
917 assert( str != NULL );
918 assert( str <= end );
921 while (str < end && (*str ==
'\t' || *str ==
'\r' || *str ==
'\n'))
925 while (str < end && (*str ==
' ' || *str ==
'\r' || *str ==
'\n'))
929 while (str < end && (*str ==
' ' || *str ==
'\t' || *str ==
'\n'))
933 while (str < end && (*str ==
' ' || *str ==
'\t' || *str ==
'\r'))
938 return impl::str_scan_nws_cpu(str, end);
940 return impl::str_scan_nws_default(str, end);
956 inline const char*
str_scan_nws_r(
const char* str,
const char* end,
char delim) {
957 assert( str != NULL );
958 assert( str <= end );
961 while (--end > str && (*end ==
'\t' || *end ==
'\r' || *end ==
'\n'));
965 while (--end > str && (*end ==
' ' || *end ==
'\r' || *end ==
'\n'));
969 while (--end > str && (*end ==
' ' || *end ==
'\t' || *end ==
'\n'));
973 while (--end > str && (*end ==
' ' || *end ==
'\t' || *end ==
'\r'));
978 return impl::str_scan_nws_cpu_r(str, end);
980 return impl::str_scan_nws_default_r(str, end);
996 inline const char*
str_scan_ndelim(
const char* str,
const char* end,
char delim1,
char delim2) {
997 assert( str != NULL );
998 assert( str <= end );
1000 return impl::str_scan_ndelim_cpu(str, end, delim1, delim2);
1002 return impl::str_scan_ndelim_default(str, end, delim1, delim2);
1018 assert( str != NULL );
1019 assert( str <= end );
1020 #if defined(EVO_CPU) 1021 return impl::str_scan_ndelim_cpu_r(str, end, delim1, delim2);
1023 return impl::str_scan_ndelim_default_r(str, end, delim1, delim2);
1037 inline const char*
str_scan_delim(
const char* str,
const char* end,
char delim1,
char delim2) {
1038 assert( str != NULL );
1039 assert( str <= end );
1040 #if defined(EVO_CPU) 1041 return impl::str_scan_delim_cpu(str, end, delim1, delim2);
1043 return impl::str_scan_delim_default(str, end, delim1, delim2);
1058 inline const char*
str_scan_delim_r(
const char* str,
const char* end,
char delim1,
char delim2) {
1059 assert( str != NULL );
1060 assert( str <= end );
1061 #if defined(EVO_CPU) 1062 return impl::str_scan_delim_cpu_r(str, end, delim1, delim2);
1064 return impl::str_scan_delim_default_r(str, end, delim1, delim2);
1079 inline const char*
str_scan_delim(
const char* str,
const char* end,
const char* delims, uint delim_count) {
1080 assert( str != NULL );
1081 assert( str <= end );
1082 assert( delim_count > 0 );
1083 #if defined(EVO_CPU) 1084 switch (delim_count) {
1086 str = (
char*)::memchr(str, delims[0], end - str);
1087 return (str == NULL ? end : str);
1090 return impl::str_scan_delim_cpu(str, end, delims[0], delims[1]);
1092 if (delim_count <= impl::SSE_BATCH_SIZE)
1093 return impl::str_scan_delim_cpu(str, end, delims, delim_count);
1097 return impl::str_scan_delim_default(str, end, delims, delim_count);
1112 inline const char*
str_scan_delim_r(
const char* str,
const char* end,
const char* delims, uint delim_count) {
1113 assert( str != NULL );
1114 assert( str <= end );
1115 assert( delim_count > 0 );
1116 #if defined(EVO_CPU) 1117 switch (delim_count) {
1120 return (end == NULL ? str : end + 1);
1123 return impl::str_scan_delim_cpu_r(str, end, delims[0], delims[1]);
1125 if (delim_count <= impl::SSE_BATCH_SIZE)
1126 return impl::str_scan_delim_cpu_r(str, end, delims, delim_count);
1130 return impl::str_scan_delim_default_r(str, end, delims, delim_count);
1144 assert( str != NULL );
1145 assert( str <= end );
1146 const char DEL_CHAR = 0x7F;
1149 str = (
char*)::memchr(str,
'`', end - str);
1152 if (*++str == DEL_CHAR)
1172 inline const char*
str_scan_endq(
const char*& startq,
const char*& endq,
const char* str,
const char* end) {
1178 assert( str < end );
1183 const char DEL_CHAR = 0x7F;
1184 if (end >= str + 4 && str[1] == DEL_CHAR) {
1188 p = (
char*)::memchr(p,
'`', end - p);
1189 if (p == NULL || p + 1 >= end)
1191 if (p[1] == DEL_CHAR) {
1201 const char q = *str;
1202 if (end >= str + 6 && str[1] == q && str[2] == q) {
1206 p = (
char*)::memchr(p, q, end - p);
1207 if (p == NULL || p + 2 >= end)
1211 while (p + 3 < end && p[3] == q)
1225 p = (
char*)::memchr(p, q, end - p);
1257 inline const char*
str_scan_endq(
const char*& startq,
const char*& endq,
const char* str,
const char* end,
char delim) {
1263 assert( str < end );
1268 const char DEL_CHAR = 0x7F;
1269 if (end >= str + 4 && str[1] == DEL_CHAR) {
1273 p = (
char*)::memchr(p,
'`', end - p);
1274 if (p == NULL || p + 1 >= end)
1276 if (p[1] == DEL_CHAR) {
1279 if (p < end && *p != delim)
1290 const char q = *str;
1291 if (end >= str + 6 && str[1] == q && str[2] == q) {
1295 p = (
char*)::memchr(p, q, end - p);
1296 if (p == NULL || p + 2 >= end)
1300 while (p + 3 < end && p[3] == q)
1304 if (p < end && *p != delim)
1318 p = (
char*)::memchr(p, q, end - p);
1323 if (p < end && *p != delim)
1336 p = (
char*)::memchr(str, delim, end - str);
1362 inline const char*
str_scan_endq_r(
const char*& startq,
const char*& endq,
const char* str,
const char* end,
char delim) {
1368 assert( str < end );
1370 const char DEL_CHAR = 0x7F;
1372 switch (*(end - 1)) {
1374 if (end >= str + 4 && *(end - 2) ==
'`') {
1378 if (p == NULL || p == str)
1383 if (p > str && *(p - 1) != delim)
1395 const char q = *(end - 1);
1396 if (end >= str + 6 && *(end - 2) == q && *(end - 3) == q) {
1401 if (p == NULL || p - 2 < str)
1405 while (p > str && *(p - 1) == q)
1409 if (p > str && *(p - 1) != delim)
1426 if (p > str && *(p - 1) != delim)
1464 inline const char*
str_scan_endq(
const char*& startq,
const char*& endq,
const char* str,
const char* end,
char delim1,
char delim2) {
1470 assert( str < end );
1475 const char DEL_CHAR = 0x7F;
1476 if (end >= str + 4 && str[1] == DEL_CHAR) {
1480 p = (
char*)::memchr(p,
'`', end - p);
1481 if (p == NULL || p + 1 >= end)
1483 if (p[1] == DEL_CHAR) {
1486 if (p < end && *p != delim1 && *p != delim2)
1497 const char q = *str;
1498 if (end >= str + 6 && str[1] == q && str[2] == q) {
1502 p = (
char*)::memchr(p, q, end - p);
1503 if (p == NULL || p + 2 >= end)
1507 while (p + 3 < end && p[3] == q)
1511 if (p < end && *p != delim1 && *p != delim2)
1525 p = (
char*)::memchr(p, q, end - p);
1530 if (p < end && *p != delim1 && *p != delim2)
1570 inline const char*
str_scan_endq(
const char*& startq,
const char*& endq,
const char* str,
const char* end,
const char* delims, uint delim_count,
char ws_delim=0) {
1576 assert( str < end );
1577 assert( delim_count > 0 );
1582 const char DEL_CHAR = 0x7F;
1583 if (end >= str + 4 && str[1] == DEL_CHAR) {
1587 p = (
char*)::memchr(p,
'`', end - p);
1588 if (p == NULL || p + 1 >= end)
1590 if (p[1] == DEL_CHAR) {
1593 if (p < end && ::memchr(delims, *p, delim_count) == NULL)
1604 const char q = *str;
1605 if (end >= str + 6 && str[1] == q && str[2] == q) {
1609 p = (
char*)::memchr(p, q, end - p);
1610 if (p == NULL || p + 2 >= end)
1614 while (p + 3 < end && p[3] == q)
1618 if (p < end && ::memchr(delims, *p, delim_count) == NULL)
1632 p = (
char*)::memchr(p, q, end - p);
1637 if (p < end && ::memchr(delims, *p, delim_count) == NULL)
1679 inline const char*
str_scan_endq_r(
const char*& startq,
const char*& endq,
const char* str,
const char* end,
const char* delims, uint delim_count,
char ws_delim=0) {
1685 assert( str < end );
1686 assert( delim_count > 0 );
1688 const char DEL_CHAR = 0x7F;
1690 switch (*(end - 1)) {
1692 if (end >= str + 4 && *(end - 2) ==
'`') {
1696 if (p == NULL || p == str)
1701 if (p > str && ::memchr(delims, *(p - 1), delim_count) == NULL)
1713 const char q = *(end - 1);
1714 if (end >= str + 6 && *(end - 2) == q && *(end - 3) == q) {
1719 if (p == NULL || p - 2 < str)
1723 while (p > str && *(p - 1) == q)
1727 if (p > str && ::memchr(delims, *(p - 1), delim_count) == NULL)
1744 if (p > str && ::memchr(delims, *(p - 1), delim_count) == NULL)
1775 inline const char*
str_scan_to(uint maxlen,
const char* str,
const char* end,
char ch) {
1778 assert( str < end );
1780 const char* maxlen_end = str + maxlen;
1781 if (maxlen_end < end)
1782 return (
char*)::memchr(str, ch, maxlen_end - str);
1784 str = (
char*)::memchr(str, ch, end - str);
1801 inline const char*
str_scan_to(uint maxlen,
const char* str,
const char* end,
char ch1,
char ch2) {
1804 assert( str < end );
1806 const char* maxlen_end = str + maxlen;
1807 if (maxlen_end < end) {
1809 if (str < maxlen_end)
1831 const char* p = str;
1832 for (; p < end; ++p) {
1834 if (ch < '0' || ch >
'9')
1837 if (num > limitbase || (num == limitbase && (T)ch > limitdig))
1856 inline const char*
str_scan_hex(T& num,
const char* str,
const char* end) {
1860 const char* p = str;
1861 for (; p < end; ++p) {
1867 }
else if (ch >=
'a') {
1871 }
else if (ch <=
'F') {
1877 if (num > limitbase)
1894 static const char DEL_CHAR = 0x7F;
1917 static Type get(
const char* data, ulong data_size) {
1920 assert( data != NULL );
1922 const uint DELIMS_COUNT = 3;
1923 const char* DELIMS =
"'\"`";
1924 const char* save_ptr[DELIMS_COUNT];
1928 for (ulong i = 0; i < DELIMS_COUNT; ++i) {
1929 p = (
char*)::memchr(data, DELIMS[i], data_size);
1936 const char* end = data + data_size - 2;
1937 for (ulong i = 0; i < DELIMS_COUNT; ++i) {
1938 const char ch = DELIMS[i];
1942 if (p[1] == ch && p[2] == ch)
1944 if ((p = (
char*)::memchr(p + 1, ch, end - p - 1)) != NULL)
1947 return (
Type)(i + DELIMS_COUNT);
1954 return tBACKTICK_DEL;
1967 static Type get(
bool& optional,
const char* data, ulong data_size,
char delim) {
1968 if (data_size == 0) {
1971 }
else if (data_size == 1) {
1972 optional = (*data != delim && *data >
' ');
1973 return (*data ==
'\'' ? tDOUBLE : tSINGLE);
1975 assert( data != NULL );
1977 bool block_backtick_del =
false;
1978 const char* end = data + data_size;
1979 const char* p = (
char*)::memchr(data, delim, data_size);
1985 if (*(end - 1) ==
'"')
1990 if (*(end - 1) ==
'\'')
1995 if (*(end - 1) ==
'\'')
1999 switch (*(end - 1)) {
2008 optional = (*data >
' ' && *(end - 1) >
' ');
2018 const uint QUOTING_SIZE = 6;
2019 char quoting[QUOTING_SIZE] = { 0, 0, 0, 0, 0, 0 };
2027 quoting[(uint)tSINGLE] = (
char)AVOID;
2028 quoting[(uint)tSINGLE3] = (
char)AVOID;
2031 quoting[(uint)tDOUBLE] = (
char)AVOID;
2032 quoting[(uint)tDOUBLE3] = (
char)AVOID;
2035 quoting[(uint)tBACKTICK] = (
char)AVOID;
2036 quoting[(uint)tBACKTICK3] = (
char)AVOID;
2046 if (data_size > 1 && data[1] == ch)
2047 quoting[(uint)tSINGLE] = (
char)BLOCK;
2049 quoting[(uint)tSINGLE] = (
char)AVOID;
2050 quoting[(uint)tSINGLE3] = (
char)AVOID;
2053 if (data_size > 1 && data[1] == ch)
2054 quoting[(uint)tDOUBLE] = (
char)BLOCK;
2056 quoting[(uint)tDOUBLE] = (
char)AVOID;
2057 quoting[(uint)tDOUBLE3] = (
char)AVOID;
2060 if (data_size > 1 && data[1] == ch)
2061 quoting[(uint)tBACKTICK] = (
char)BLOCK;
2063 quoting[(uint)tBACKTICK] = (
char)AVOID;
2064 quoting[(uint)tBACKTICK3] = (
char)AVOID;
2071 const char* data_plus_3 = data + 3;
2077 quoting[(uint)tSINGLE] = (
char)BLOCK;
2078 if (p >= data_plus_3 && *(p - 2) == ch && *(p - 3) == ch)
2079 quoting[(uint)tSINGLE3] = (
char)BLOCK;
2082 quoting[(uint)tDOUBLE] = 1;
2083 if (p >= data_plus_3 && *(p - 2) == ch && *(p - 3) == ch)
2084 quoting[(uint)tDOUBLE3] = (
char)BLOCK;
2087 quoting[(uint)tBACKTICK] = 1;
2088 if (p >= data_plus_3 && *(p - 2) == ch && *(p - 3) == ch)
2089 quoting[(uint)tBACKTICK3] = (
char)BLOCK;
2092 if (p >= data + 2 && *(p - 2) ==
'`')
2093 block_backtick_del =
true;
2100 p = (
char*)::memchr(p, delim, end - p);
2101 }
while (p != NULL);
2104 p = (
char*)::memchr(quoting, ALLOW, QUOTING_SIZE);
2106 return (
Type)(p - quoting);
2109 p = (
char*)::memchr(quoting, AVOID, QUOTING_SIZE);
2111 return (
Type)(p - quoting);
2115 if (block_backtick_del)
2117 return tBACKTICK_DEL;
2129 static Type get(
const char* data, ulong data_size,
char delim) {
2131 return get(optional, data, data_size, delim);
2144 static Type get(
const char* data, ulong data_size,
char delim1,
char delim2) {
2147 else if (data_size == 1)
2148 return (*data ==
'\'' ? tDOUBLE : tSINGLE);
2149 assert( data != NULL );
2151 bool block_backtick_del =
false;
2152 const char* end = data + data_size;
2158 if (*(end - 1) ==
'"')
2162 if (*(end - 1) ==
'\'')
2166 if (*(end - 1) ==
'\'')
2170 switch (*(end - 1)) {
2186 const uint QUOTING_SIZE = 6;
2187 char quoting[QUOTING_SIZE] = { 0, 0, 0, 0, 0, 0 };
2194 quoting[(uint)tSINGLE] = (
char)AVOID;
2195 quoting[(uint)tSINGLE3] = (
char)AVOID;
2198 quoting[(uint)tDOUBLE] = (
char)AVOID;
2199 quoting[(uint)tDOUBLE3] = (
char)AVOID;
2202 quoting[(uint)tBACKTICK] = (
char)AVOID;
2203 quoting[(uint)tBACKTICK3] = (
char)AVOID;
2213 if (data_size > 1 && data[1] == ch)
2214 quoting[(uint)tSINGLE] = (
char)BLOCK;
2216 quoting[(uint)tSINGLE] = (
char)AVOID;
2217 quoting[(uint)tSINGLE3] = (
char)AVOID;
2220 if (data_size > 1 && data[1] == ch)
2221 quoting[(uint)tDOUBLE] = (
char)BLOCK;
2223 quoting[(uint)tDOUBLE] = (
char)AVOID;
2224 quoting[(uint)tDOUBLE3] = (
char)AVOID;
2227 if (data_size > 1 && data[1] == ch)
2228 quoting[(uint)tBACKTICK] = (
char)BLOCK;
2230 quoting[(uint)tBACKTICK] = (
char)AVOID;
2231 quoting[(uint)tBACKTICK3] = (
char)AVOID;
2238 const char* data_plus_3 = data + 3;
2244 quoting[(uint)tSINGLE] = (
char)BLOCK;
2245 if (p >= data_plus_3 && *(p - 2) == ch && *(p - 3) == ch)
2246 quoting[(uint)tSINGLE3] = (
char)BLOCK;
2249 quoting[(uint)tDOUBLE] = 1;
2250 if (p >= data_plus_3 && *(p - 2) == ch && *(p - 3) == ch)
2251 quoting[(uint)tDOUBLE3] = (
char)BLOCK;
2254 quoting[(uint)tBACKTICK] = 1;
2255 if (p >= data_plus_3 && *(p - 2) == ch && *(p - 3) == ch)
2256 quoting[(uint)tBACKTICK3] = (
char)BLOCK;
2259 if (p >= data + 2 && *(p - 2) ==
'`')
2260 block_backtick_del =
true;
2270 p = (
char*)::memchr(quoting, ALLOW, QUOTING_SIZE);
2272 return (
Type)(p - quoting);
2275 p = (
char*)::memchr(quoting, AVOID, QUOTING_SIZE);
2277 return (
Type)(p - quoting);
2281 if (block_backtick_del)
2283 return tBACKTICK_DEL;
const char * str_scan_endq_r(const char *&startq, const char *&endq, const char *str, const char *end, char delim)
Scan string pointer in reverse and extract quoted or unquoted text with a delimiter and return new en...
Definition: strscan.h:1362
const char * str_scan_delim(const char *str, const char *end, char delim1, char delim2)
Scan string pointer for next delimiter and return stop pointer.
Definition: strscan.h:1037
const char * str_scan_ndelim(const char *str, const char *end, char delim1, char delim2)
Scan string pointer for next non-delimiter and return stop pointer.
Definition: strscan.h:996
Single-quotes: '
Definition: strscan.h:1898
Backtick: `
Definition: strscan.h:1900
Triple backtick: ```
Definition: strscan.h:1903
Triple single-quotes: '''
Definition: strscan.h:1901
Evo implementation detail: String helpers.
bool str_scan_backtickdel(const char *str, const char *end)
Scan string for a Backtick + DEL pair.
Definition: strscan.h:1143
const char * str_scan_nws(const char *str, const char *end)
Scan string pointer for next non-whitespace character and return stop pointer.
Definition: strscan.h:877
Basic integer type.
Definition: type.h:980
const char * string_memrchr(const char *str, char ch, size_t size)
Evo implementation of memrchr() to search for character in reverse.
Definition: str.h:1150
const char * str_scan_to(uint maxlen, const char *str, const char *end, char ch)
Scan string pointer for char and return stop pointer.
Definition: strscan.h:1775
const char * str_scan_nws_r(const char *str, const char *end)
Scan string pointer for next non-whitespace character in reverse and return new end after stop pointe...
Definition: strscan.h:896
const char * str_scan_endq(const char *&startq, const char *&endq, const char *str, const char *end)
Scan string pointer and extract quoted or unquoted text.
Definition: strscan.h:1172
static const int BITS
Type size in bits.
Definition: type.h:986
Double-quotes: "
Definition: strscan.h:1899
Triple double-quotes: """
Definition: strscan.h:1902
Evo C++ Library namespace.
Definition: alg.h:11
const char * str_scan_decimal(T &num, const char *str, const char *end)
Scan string pointer for decimal number and return stop pointer.
Definition: strscan.h:1826
Backtick followed by DEL char (7F) – last resort (rare)
Definition: strscan.h:1904
const char * str_scan_ndelim_r(const char *str, const char *end, char delim1, char delim2)
Scan string pointer for next non-delimiter in reverse and return new end after stop pointer...
Definition: strscan.h:1017
const char * str_scan_hex(T &num, const char *str, const char *end)
Scan string pointer for hex number and return stop pointer.
Definition: strscan.h:1856
const char * str_scan_delim_r(const char *str, const char *end, char delim1, char delim2)
Scan string pointer for next delimiter in reverse and return new end after stop pointer.
Definition: strscan.h:1058
Helpers for determining quoting type to use with string data.
Definition: strscan.h:1893
Evo basic types and traits.
Type
Quoting type.
Definition: strscan.h:1897