847
848
849
850
851
852
853
854
855
856
857
858
859
860
|
}
i++;
}
}
return i;
}
/*
*---------------------------------------------------------------------------
*
* Tcl_UtfFindFirst --
*
* Returns a pointer to the first occurrence of the given Unicode character
* in the NULL-terminated UTF-8 string. The NULL terminator is considered
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
|
}
i++;
}
}
return i;
}
size_t
TclNumUtfChars(
const char *src, /* The UTF-8 string to measure. */
size_t length) /* The length of the string in bytes, or
* TCL_INDEX_NONE for strlen(src). */
{
unsigned short ch = 0;
size_t i = 0;
if (length == TCL_INDEX_NONE) {
/* string is NUL-terminated, so TclUtfToUniChar calls are safe. */
while (*src != '\0') {
src += Tcl_UtfToChar16(src, &ch);
i++;
}
} else {
/* Will return value between 0 and length. No overflow checks. */
/* Pointer to the end of string. Never read endPtr[0] */
const char *endPtr = src + length;
/* Pointer to last byte where optimization still can be used */
const char *optPtr = endPtr - 4;
/*
* Optimize away the call in this loop. Justified because...
* when (src <= optPtr), (endPtr - src) >= (endPtr - optPtr)
* By initialization above (endPtr - optPtr) = TCL_UTF_MAX
* So (endPtr - src) >= TCL_UTF_MAX, and passing that to
* Tcl_UtfCharComplete we know will cause return of 1.
*/
while (src <= optPtr
/* && Tcl_UtfCharComplete(src, endPtr - src) */ ) {
src += Tcl_UtfToChar16(src, &ch);
i++;
}
/* Loop over the remaining string where call must happen */
while (src < endPtr) {
if (Tcl_UtfCharComplete(src, endPtr - src)) {
src += Tcl_UtfToChar16(src, &ch);
} else {
/*
* src points to incomplete UTF-8 sequence
* Treat first byte as character and count it
*/
src++;
}
i++;
}
}
return i;
}
/*
*---------------------------------------------------------------------------
*
* Tcl_UtfFindFirst --
*
* Returns a pointer to the first occurrence of the given Unicode character
* in the NULL-terminated UTF-8 string. The NULL terminator is considered
|
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
|
*/
const char *
Tcl_UtfAtIndex(
const char *src, /* The UTF-8 string. */
ssize_t index) /* The position of the desired character. */
{
Tcl_UniChar ch = 0;
#if TCL_UTF_MAX < 4
size_t len = 0;
#endif
if (index != TCL_INDEX_NONE) {
while (index--) {
#if TCL_UTF_MAX < 4
src += (len = TclUtfToUniChar(src, &ch));
#else
src += TclUtfToUniChar(src, &ch);
#endif
}
#if TCL_UTF_MAX < 4
if ((ch >= 0xD800) && (len < 3)) {
/* Index points at character following high Surrogate */
src += TclUtfToUniChar(src, &ch);
}
#endif
}
return src;
}
/*
*---------------------------------------------------------------------------
*
* Tcl_UtfBackslash --
*
* Figure out how to handle a backslash sequence.
*
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
<
<
|
<
<
<
<
|
|
|
|
<
|
|
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
|
*/
const char *
Tcl_UtfAtIndex(
const char *src, /* The UTF-8 string. */
ssize_t index) /* The position of the desired character. */
{
int ch = 0;
if (index != TCL_INDEX_NONE) {
while (index--) {
/* Make use of the #undef Tcl_UtfToUniChar above, which already handles UCS4. */
src += Tcl_UtfToUniChar(src, &ch);
}
}
return src;
}
const char *
TclUtfAtIndex(
const char *src, /* The UTF-8 string. */
size_t index) /* The position of the desired character. */
{
unsigned short ch = 0;
size_t len = 0;
if (index != TCL_INDEX_NONE) {
while (index--) {
src += (len = Tcl_UtfToChar16(src, &ch));
}
if ((ch >= 0xD800) && (len < 3)) {
/* Index points at character following high Surrogate */
src += Tcl_UtfToChar16(src, &ch);
}
}
return src;
}
/*
*---------------------------------------------------------------------------
*
* Tcl_UtfBackslash --
*
* Figure out how to handle a backslash sequence.
*
|