Branch data Line data Source code
1 : : /* Finding the optimal width of unicode characters in a buffer */ 2 : : 3 : : #if !STRINGLIB_IS_UNICODE 4 : : # error "find_max_char.h is specific to Unicode" 5 : : #endif 6 : : 7 : : /* Mask to quickly check whether a C 'size_t' contains a 8 : : non-ASCII, UTF8-encoded char. */ 9 : : #if (SIZEOF_SIZE_T == 8) 10 : : # define UCS1_ASCII_CHAR_MASK 0x8080808080808080ULL 11 : : #elif (SIZEOF_SIZE_T == 4) 12 : : # define UCS1_ASCII_CHAR_MASK 0x80808080U 13 : : #else 14 : : # error C 'size_t' size should be either 4 or 8! 15 : : #endif 16 : : 17 : : #if STRINGLIB_SIZEOF_CHAR == 1 18 : : 19 : : Py_LOCAL_INLINE(Py_UCS4) 20 : 43500562 : STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end) 21 : : { 22 : 43500562 : const unsigned char *p = (const unsigned char *) begin; 23 : : 24 [ + + ]: 315340075 : while (p < end) { 25 [ + + ]: 275316864 : if (_Py_IS_ALIGNED(p, ALIGNOF_SIZE_T)) { 26 : : /* Help register allocation */ 27 : 37431577 : const unsigned char *_p = p; 28 [ + + ]: 148476063 : while (_p + SIZEOF_SIZE_T <= end) { 29 : 111088096 : size_t value = *(const size_t *) _p; 30 [ + + ]: 111088096 : if (value & UCS1_ASCII_CHAR_MASK) 31 : 43610 : return 255; 32 : 111044486 : _p += SIZEOF_SIZE_T; 33 : : } 34 : 37387967 : p = _p; 35 [ + + ]: 37387967 : if (p == end) 36 : 3411616 : break; 37 : : } 38 [ + + ]: 271861638 : if (*p++ & 0x80) 39 : 22125 : return 255; 40 : : } 41 : 43434827 : return 127; 42 : : } 43 : : 44 : : #undef ASCII_CHAR_MASK 45 : : 46 : : #else /* STRINGLIB_SIZEOF_CHAR == 1 */ 47 : : 48 : : #define MASK_ASCII 0xFFFFFF80 49 : : #define MASK_UCS1 0xFFFFFF00 50 : : #define MASK_UCS2 0xFFFF0000 51 : : 52 : : #define MAX_CHAR_ASCII 0x7f 53 : : #define MAX_CHAR_UCS1 0xff 54 : : #define MAX_CHAR_UCS2 0xffff 55 : : #define MAX_CHAR_UCS4 0x10ffff 56 : : 57 : : Py_LOCAL_INLINE(Py_UCS4) 58 : 581088 : STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end) 59 : : { 60 : : #if STRINGLIB_SIZEOF_CHAR == 2 61 : 283237 : const Py_UCS4 mask_limit = MASK_UCS1; 62 : 283237 : const Py_UCS4 max_char_limit = MAX_CHAR_UCS2; 63 : : #elif STRINGLIB_SIZEOF_CHAR == 4 64 : 297851 : const Py_UCS4 mask_limit = MASK_UCS2; 65 : 297851 : const Py_UCS4 max_char_limit = MAX_CHAR_UCS4; 66 : : #else 67 : : #error Invalid STRINGLIB_SIZEOF_CHAR (must be 1, 2 or 4) 68 : : #endif 69 : : Py_UCS4 mask; 70 : 581088 : Py_ssize_t n = end - begin; 71 : 581088 : const STRINGLIB_CHAR *p = begin; 72 : 581088 : const STRINGLIB_CHAR *unrolled_end = begin + _Py_SIZE_ROUND_DOWN(n, 4); 73 : : Py_UCS4 max_char; 74 : : 75 : 581088 : max_char = MAX_CHAR_ASCII; 76 : 581088 : mask = MASK_ASCII; 77 [ + + ]: 24203859 : while (p < unrolled_end) { 78 : 23739445 : STRINGLIB_CHAR bits = p[0] | p[1] | p[2] | p[3]; 79 [ + + ]: 23739445 : if (bits & mask) { 80 [ + + ]: 291540 : if (mask == mask_limit) { 81 : : /* Limit reached */ 82 : 116674 : return max_char_limit; 83 : : } 84 [ + + ]: 174866 : if (mask == MASK_ASCII) { 85 : 140394 : max_char = MAX_CHAR_UCS1; 86 : 140394 : mask = MASK_UCS1; 87 : : } 88 : : else { 89 : : /* mask can't be MASK_UCS2 because of mask_limit above */ 90 : : assert(mask == MASK_UCS1); 91 : 34472 : max_char = MAX_CHAR_UCS2; 92 : 34472 : mask = MASK_UCS2; 93 : : } 94 : : /* We check the new mask on the same chars in the next iteration */ 95 : 174866 : continue; 96 : : } 97 : 23447905 : p += 4; 98 : : } 99 [ + + ]: 1585100 : while (p < end) { 100 [ + + ]: 1148678 : if (p[0] & mask) { 101 [ + + ]: 314369 : if (mask == mask_limit) { 102 : : /* Limit reached */ 103 : 27992 : return max_char_limit; 104 : : } 105 [ + + ]: 286377 : if (mask == MASK_ASCII) { 106 : 156596 : max_char = MAX_CHAR_UCS1; 107 : 156596 : mask = MASK_UCS1; 108 : : } 109 : : else { 110 : : /* mask can't be MASK_UCS2 because of mask_limit above */ 111 : : assert(mask == MASK_UCS1); 112 : 129781 : max_char = MAX_CHAR_UCS2; 113 : 129781 : mask = MASK_UCS2; 114 : : } 115 : : /* We check the new mask on the same chars in the next iteration */ 116 : 286377 : continue; 117 : : } 118 : 834309 : p++; 119 : : } 120 : 436422 : return max_char; 121 : : } 122 : : 123 : : #undef MASK_ASCII 124 : : #undef MASK_UCS1 125 : : #undef MASK_UCS2 126 : : #undef MAX_CHAR_ASCII 127 : : #undef MAX_CHAR_UCS1 128 : : #undef MAX_CHAR_UCS2 129 : : #undef MAX_CHAR_UCS4 130 : : 131 : : #endif /* STRINGLIB_SIZEOF_CHAR == 1 */ 132 : :