This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [ID 20010309.004] my-variables lose values while goto'ing within a for(;;)-loop
[perl5.git] / utf8.c
CommitLineData
a0ed51b3
LW
1/* utf8.c
2 *
bc89e66f 3 * Copyright (c) 1998-2001, Larry Wall
a0ed51b3
LW
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/*
11 * 'What a fix!' said Sam. 'That's the one place in all the lands we've ever
12 * heard of that we don't want to see any closer; and that's the one place
13 * we're trying to get to! And that's just where we can't get, nohow.'
14 *
15 * 'Well do I understand your speech,' he answered in the same language;
16 * 'yet few strangers do so. Why then do you not speak in the Common Tongue,
17 * as is the custom in the West, if you wish to be answered?'
18 *
19 * ...the travellers perceived that the floor was paved with stones of many
20 * hues; branching runes and strange devices intertwined beneath their feet.
21 */
22
23#include "EXTERN.h"
864dbfa3 24#define PERL_IN_UTF8_C
a0ed51b3
LW
25#include "perl.h"
26
27/* Unicode support */
28
eebe1485 29/*
9041c2e3 30=for apidoc A|U8*|uvuni_to_utf8|U8 *d|UV uv
eebe1485
SC
31
32Adds the UTF8 representation of the Unicode codepoint C<uv> to the end
33of the string C<d>; C<d> should be have at least C<UTF8_MAXLEN+1> free
34bytes available. The return value is the pointer to the byte after the
9041c2e3 35end of the new character. In other words,
eebe1485 36
9041c2e3 37 d = uvuni_to_utf8(d, uv);
eebe1485
SC
38
39is the recommended Unicode-aware way of saying
40
41 *(d++) = uv;
42
43=cut
44*/
45
dfe13c55 46U8 *
9041c2e3 47Perl_uvuni_to_utf8(pTHX_ U8 *d, UV uv)
a0ed51b3
LW
48{
49 if (uv < 0x80) {
50 *d++ = uv;
51 return d;
52 }
53 if (uv < 0x800) {
54 *d++ = (( uv >> 6) | 0xc0);
55 *d++ = (( uv & 0x3f) | 0x80);
56 return d;
57 }
58 if (uv < 0x10000) {
59 *d++ = (( uv >> 12) | 0xe0);
60 *d++ = (((uv >> 6) & 0x3f) | 0x80);
61 *d++ = (( uv & 0x3f) | 0x80);
62 return d;
63 }
64 if (uv < 0x200000) {
65 *d++ = (( uv >> 18) | 0xf0);
66 *d++ = (((uv >> 12) & 0x3f) | 0x80);
67 *d++ = (((uv >> 6) & 0x3f) | 0x80);
68 *d++ = (( uv & 0x3f) | 0x80);
69 return d;
70 }
71 if (uv < 0x4000000) {
72 *d++ = (( uv >> 24) | 0xf8);
73 *d++ = (((uv >> 18) & 0x3f) | 0x80);
74 *d++ = (((uv >> 12) & 0x3f) | 0x80);
75 *d++ = (((uv >> 6) & 0x3f) | 0x80);
76 *d++ = (( uv & 0x3f) | 0x80);
77 return d;
78 }
79 if (uv < 0x80000000) {
80 *d++ = (( uv >> 30) | 0xfc);
81 *d++ = (((uv >> 24) & 0x3f) | 0x80);
82 *d++ = (((uv >> 18) & 0x3f) | 0x80);
83 *d++ = (((uv >> 12) & 0x3f) | 0x80);
84 *d++ = (((uv >> 6) & 0x3f) | 0x80);
85 *d++ = (( uv & 0x3f) | 0x80);
86 return d;
87 }
6b8eaf93 88#ifdef HAS_QUAD
d7578b48 89 if (uv < UTF8_QUAD_MAX)
a0ed51b3
LW
90#endif
91 {
92 *d++ = 0xfe; /* Can't match U+FEFF! */
93 *d++ = (((uv >> 30) & 0x3f) | 0x80);
94 *d++ = (((uv >> 24) & 0x3f) | 0x80);
95 *d++ = (((uv >> 18) & 0x3f) | 0x80);
96 *d++ = (((uv >> 12) & 0x3f) | 0x80);
97 *d++ = (((uv >> 6) & 0x3f) | 0x80);
98 *d++ = (( uv & 0x3f) | 0x80);
99 return d;
100 }
6b8eaf93 101#ifdef HAS_QUAD
a0ed51b3
LW
102 {
103 *d++ = 0xff; /* Can't match U+FFFE! */
3c77ea2b
GS
104 *d++ = 0x80; /* 6 Reserved bits */
105 *d++ = (((uv >> 60) & 0x0f) | 0x80); /* 2 Reserved bits */
106 *d++ = (((uv >> 54) & 0x3f) | 0x80);
107 *d++ = (((uv >> 48) & 0x3f) | 0x80);
108 *d++ = (((uv >> 42) & 0x3f) | 0x80);
a0ed51b3
LW
109 *d++ = (((uv >> 36) & 0x3f) | 0x80);
110 *d++ = (((uv >> 30) & 0x3f) | 0x80);
111 *d++ = (((uv >> 24) & 0x3f) | 0x80);
112 *d++ = (((uv >> 18) & 0x3f) | 0x80);
113 *d++ = (((uv >> 12) & 0x3f) | 0x80);
114 *d++ = (((uv >> 6) & 0x3f) | 0x80);
115 *d++ = (( uv & 0x3f) | 0x80);
116 return d;
117 }
118#endif
119}
120
eebe1485 121/*
9041c2e3
NIS
122=for apidoc A|U8*|uvchr_to_utf8|U8 *d|UV uv
123
124Adds the UTF8 representation of the Native codepoint C<uv> to the end
125of the string C<d>; C<d> should be have at least C<UTF8_MAXLEN+1> free
126bytes available. The return value is the pointer to the byte after the
127end of the new character. In other words,
128
129 d = uvchr_to_utf8(d, uv);
130
131is the recommended wide native character-aware way of saying
132
133 *(d++) = uv;
134
135=cut
136*/
137
138U8 *
139Perl_uvchr_to_utf8(pTHX_ U8 *d, UV uv)
140{
141 if (uv < 0x100)
142 uv = NATIVE_TO_ASCII(uv);
143 return Perl_uvuni_to_utf8(aTHX_ d, uv);
144}
145
146
147/*
eebe1485
SC
148=for apidoc A|STRLEN|is_utf8_char|U8 *s
149
5da9da9e
JH
150Tests if some arbitrary number of bytes begins in a valid UTF-8
151character. Note that an ASCII character is a valid UTF-8 character.
152The actual number of bytes in the UTF-8 character will be returned if
153it is valid, otherwise 0.
9041c2e3 154
5da9da9e 155=cut */
067a85ef 156STRLEN
386d01d6
GS
157Perl_is_utf8_char(pTHX_ U8 *s)
158{
159 U8 u = *s;
067a85ef
A
160 STRLEN slen, len;
161 UV uv, ouv;
386d01d6 162
60006e79 163 if (UTF8_IS_ASCII(u))
386d01d6
GS
164 return 1;
165
60006e79 166 if (!UTF8_IS_START(u))
386d01d6
GS
167 return 0;
168
9f07fdcd 169 len = UTF8SKIP(s);
386d01d6 170
60006e79 171 if (len < 2 || !UTF8_IS_CONTINUATION(s[1]))
067a85ef
A
172 return 0;
173
386d01d6
GS
174 slen = len - 1;
175 s++;
067a85ef
A
176 uv = u;
177 ouv = uv;
386d01d6 178 while (slen--) {
60006e79 179 if (!UTF8_IS_CONTINUATION(*s))
386d01d6 180 return 0;
8850bf83 181 uv = UTF8_ACCUMULATE(uv, *s);
067a85ef
A
182 if (uv < ouv)
183 return 0;
184 ouv = uv;
386d01d6
GS
185 s++;
186 }
067a85ef 187
5bbb0b5a 188 if (UNISKIP(uv) < len)
067a85ef
A
189 return 0;
190
386d01d6
GS
191 return len;
192}
193
6662521e 194/*
eebe1485 195=for apidoc A|bool|is_utf8_string|U8 *s|STRLEN len
6662521e 196
5da9da9e
JH
197Returns true if first C<len> bytes of the given string form a valid UTF8
198string, false otherwise. Note that 'a valid UTF8 string' does not mean
199'a string that contains UTF8' because a valid ASCII string is a valid
200UTF8 string.
6662521e
GS
201
202=cut
203*/
204
8e84507e 205bool
6662521e
GS
206Perl_is_utf8_string(pTHX_ U8 *s, STRLEN len)
207{
067a85ef 208 U8* x = s;
1aa99e6b 209 U8* send;
067a85ef
A
210 STRLEN c;
211
1aa99e6b 212 if (!len)
6cd5fe39 213 len = strlen((char *)s);
1aa99e6b
IH
214 send = s + len;
215
6662521e
GS
216 while (x < send) {
217 c = is_utf8_char(x);
067a85ef
A
218 if (!c)
219 return FALSE;
6662521e 220 x += c;
6662521e 221 }
60006e79
JH
222 if (x != send)
223 return FALSE;
067a85ef
A
224
225 return TRUE;
6662521e
GS
226}
227
67e989fb 228/*
9041c2e3 229=for apidoc A|UV|utf8n_to_uvuni|U8 *s|STRLEN curlen|STRLEN *retlen|U32 flags
67e989fb 230
9041c2e3
NIS
231Bottom level UTF-8 decode routine.
232Returns the unicode code point value of the first character in the string C<s>
ba210ebe 233which is assumed to be in UTF8 encoding and no longer than C<curlen>;
7df053ec 234C<retlen> will be set to the length, in bytes, of that character.
67e989fb
JH
235
236If C<s> does not point to a well-formed UTF8 character, the behaviour
dcad2880
JH
237is dependent on the value of C<flags>: if it contains UTF8_CHECK_ONLY,
238it is assumed that the caller will raise a warning, and this function
28d3d195
JH
239will silently just set C<retlen> to C<-1> and return zero. If the
240C<flags> does not contain UTF8_CHECK_ONLY, warnings about
241malformations will be given, C<retlen> will be set to the expected
242length of the UTF-8 character in bytes, and zero will be returned.
243
244The C<flags> can also contain various flags to allow deviations from
245the strict UTF-8 encoding (see F<utf8.h>).
67e989fb 246
9041c2e3
NIS
247Most code should use utf8_to_uvchr() rather than call this directly.
248
dcad2880 249=cut */
67e989fb 250
a0ed51b3 251UV
9041c2e3 252Perl_utf8n_to_uvuni(pTHX_ U8* s, STRLEN curlen, STRLEN* retlen, U32 flags)
a0ed51b3 253{
ba210ebe
JH
254 UV uv = *s, ouv;
255 STRLEN len = 1;
256 bool dowarn = ckWARN_d(WARN_UTF8);
257 STRLEN expectlen = 0;
a0dbb045
JH
258 U32 warning = 0;
259
260/* This list is a superset of the UTF8_ALLOW_XXX. */
261
262#define UTF8_WARN_EMPTY 1
263#define UTF8_WARN_CONTINUATION 2
264#define UTF8_WARN_NON_CONTINUATION 3
265#define UTF8_WARN_FE_FF 4
266#define UTF8_WARN_SHORT 5
267#define UTF8_WARN_OVERFLOW 6
268#define UTF8_WARN_SURROGATE 7
269#define UTF8_WARN_BOM 8
270#define UTF8_WARN_LONG 9
271#define UTF8_WARN_FFFF 10
272
273 if (curlen == 0 &&
274 !(flags & UTF8_ALLOW_EMPTY)) {
275 warning = UTF8_WARN_EMPTY;
0c443dc2
JH
276 goto malformed;
277 }
278
421a8bf2 279 if (UTF8_IS_ASCII(uv)) {
a0ed51b3
LW
280 if (retlen)
281 *retlen = 1;
9041c2e3 282 return (UV) (*s);
a0ed51b3 283 }
67e989fb 284
421a8bf2 285 if (UTF8_IS_CONTINUATION(uv) &&
fcc8fcf6 286 !(flags & UTF8_ALLOW_CONTINUATION)) {
a0dbb045 287 warning = UTF8_WARN_CONTINUATION;
ba210ebe
JH
288 goto malformed;
289 }
290
421a8bf2 291 if (UTF8_IS_START(uv) && curlen > 1 && !UTF8_IS_CONTINUATION(s[1]) &&
fcc8fcf6 292 !(flags & UTF8_ALLOW_NON_CONTINUATION)) {
a0dbb045 293 warning = UTF8_WARN_NON_CONTINUATION;
ba210ebe
JH
294 goto malformed;
295 }
9041c2e3 296
fcc8fcf6
JH
297 if ((uv == 0xfe || uv == 0xff) &&
298 !(flags & UTF8_ALLOW_FE_FF)) {
a0dbb045 299 warning = UTF8_WARN_FE_FF;
ba210ebe 300 goto malformed;
a0ed51b3 301 }
fcc8fcf6 302
ba210ebe
JH
303 if (!(uv & 0x20)) { len = 2; uv &= 0x1f; }
304 else if (!(uv & 0x10)) { len = 3; uv &= 0x0f; }
305 else if (!(uv & 0x08)) { len = 4; uv &= 0x07; }
306 else if (!(uv & 0x04)) { len = 5; uv &= 0x03; }
307 else if (!(uv & 0x02)) { len = 6; uv &= 0x01; }
308 else if (!(uv & 0x01)) { len = 7; uv = 0; }
3c77ea2b 309 else { len = 13; uv = 0; } /* whoa! */
fcc8fcf6 310
a0ed51b3
LW
311 if (retlen)
312 *retlen = len;
9041c2e3 313
ba210ebe
JH
314 expectlen = len;
315
fcc8fcf6
JH
316 if ((curlen < expectlen) &&
317 !(flags & UTF8_ALLOW_SHORT)) {
a0dbb045 318 warning = UTF8_WARN_SHORT;
ba210ebe
JH
319 goto malformed;
320 }
321
322 len--;
a0ed51b3 323 s++;
ba210ebe
JH
324 ouv = uv;
325
a0ed51b3 326 while (len--) {
421a8bf2
JH
327 if (!UTF8_IS_CONTINUATION(*s) &&
328 !(flags & UTF8_ALLOW_NON_CONTINUATION)) {
a0dbb045
JH
329 s--;
330 warning = UTF8_WARN_NON_CONTINUATION;
ba210ebe 331 goto malformed;
a0ed51b3
LW
332 }
333 else
8850bf83 334 uv = UTF8_ACCUMULATE(uv, *s);
a0dbb045
JH
335 if (!(uv > ouv)) {
336 /* These cannot be allowed. */
337 if (uv == ouv) {
338 if (!(flags & UTF8_ALLOW_LONG)) {
339 warning = UTF8_WARN_LONG;
340 goto malformed;
341 }
342 }
343 else { /* uv < ouv */
344 /* This cannot be allowed. */
345 warning = UTF8_WARN_OVERFLOW;
346 goto malformed;
347 }
ba210ebe
JH
348 }
349 s++;
350 ouv = uv;
351 }
352
421a8bf2 353 if (UNICODE_IS_SURROGATE(uv) &&
fcc8fcf6 354 !(flags & UTF8_ALLOW_SURROGATE)) {
a0dbb045 355 warning = UTF8_WARN_SURROGATE;
ba210ebe 356 goto malformed;
421a8bf2 357 } else if (UNICODE_IS_BYTE_ORDER_MARK(uv) &&
fcc8fcf6 358 !(flags & UTF8_ALLOW_BOM)) {
a0dbb045 359 warning = UTF8_WARN_BOM;
ba210ebe 360 goto malformed;
fcc8fcf6
JH
361 } else if ((expectlen > UNISKIP(uv)) &&
362 !(flags & UTF8_ALLOW_LONG)) {
a0dbb045 363 warning = UTF8_WARN_LONG;
ba210ebe 364 goto malformed;
421a8bf2 365 } else if (UNICODE_IS_ILLEGAL(uv) &&
a9917092 366 !(flags & UTF8_ALLOW_FFFF)) {
a0dbb045 367 warning = UTF8_WARN_FFFF;
a9917092 368 goto malformed;
a0ed51b3 369 }
ba210ebe 370
a0ed51b3 371 return uv;
ba210ebe
JH
372
373malformed:
374
fcc8fcf6 375 if (flags & UTF8_CHECK_ONLY) {
ba210ebe 376 if (retlen)
cc366d4b 377 *retlen = -1;
ba210ebe
JH
378 return 0;
379 }
380
a0dbb045
JH
381 if (dowarn) {
382 SV* sv = sv_2mortal(newSVpv("Malformed UTF-8 character ", 0));
383
384 switch (warning) {
385 case 0: /* Intentionally empty. */ break;
386 case UTF8_WARN_EMPTY:
387 Perl_sv_catpvf(aTHX_ sv, "(empty string)");
388 break;
389 case UTF8_WARN_CONTINUATION:
390 Perl_sv_catpvf(aTHX_ sv, "(unexpected continuation byte 0x%02"UVxf")", uv);
391 break;
392 case UTF8_WARN_NON_CONTINUATION:
393 Perl_sv_catpvf(aTHX_ sv, "(unexpected non-continuation byte 0x%02"UVxf" after start byte 0x%02"UVxf")",
394 (UV)s[1], uv);
395 break;
396 case UTF8_WARN_FE_FF:
397 Perl_sv_catpvf(aTHX_ sv, "(byte 0x%02"UVxf")", uv);
398 break;
399 case UTF8_WARN_SHORT:
400 Perl_sv_catpvf(aTHX_ sv, "(%d byte%s, need %d)",
401 curlen, curlen == 1 ? "" : "s", expectlen);
402 break;
403 case UTF8_WARN_OVERFLOW:
404 Perl_sv_catpvf(aTHX_ sv, "(overflow at 0x%"UVxf", byte 0x%02x)",
405 ouv, *s);
406 break;
407 case UTF8_WARN_SURROGATE:
408 Perl_sv_catpvf(aTHX_ sv, "(UTF-16 surrogate 0x%04"UVxf")", uv);
409 break;
410 case UTF8_WARN_BOM:
411 Perl_sv_catpvf(aTHX_ sv, "(byte order mark 0x%04"UVxf")", uv);
412 break;
413 case UTF8_WARN_LONG:
414 Perl_sv_catpvf(aTHX_ sv, "(%d byte%s, need %d)",
415 expectlen, expectlen == 1 ? "": "s", UNISKIP(uv));
416 break;
417 case UTF8_WARN_FFFF:
418 Perl_sv_catpvf(aTHX_ sv, "(character 0x%04"UVxf")", uv);
419 break;
420 default:
421 Perl_sv_catpvf(aTHX_ sv, "(unknown reason)");
422 break;
423 }
424
425 if (warning) {
426 char *s = SvPVX(sv);
427
428 if (PL_op)
429 Perl_warner(aTHX_ WARN_UTF8,
430 "%s in %s", s, PL_op_desc[PL_op->op_type]);
431 else
432 Perl_warner(aTHX_ WARN_UTF8, "%s", s);
433 }
434 }
435
ba210ebe 436 if (retlen)
28d3d195 437 *retlen = expectlen ? expectlen : len;
ba210ebe 438
28d3d195 439 return 0;
a0ed51b3
LW
440}
441
8e84507e 442/*
9041c2e3 443=for apidoc A|U8* s|utf8n_to_uvchr|STRLEN curlen, STRLEN *retlen, U32 flags
8e84507e 444
9041c2e3 445Returns the native character value of the first character in the string C<s>
8e84507e 446which is assumed to be in UTF8 encoding; C<retlen> will be set to the
7df053ec 447length, in bytes, of that character.
8e84507e 448
9041c2e3
NIS
449Allows length and flags to be passed to low level routine.
450
451=cut
452*/
453
454UV
455Perl_utf8n_to_uvchr(pTHX_ U8* s, STRLEN curlen, STRLEN* retlen, U32 flags)
456{
457 UV uv = Perl_utf8n_to_uvuni(aTHX_ s, curlen, retlen, flags);
458 if (uv < 0x100)
459 return (UV) ASCII_TO_NATIVE(uv);
460 return uv;
461}
462
463/*
464=for apidoc A|U8* s|utf8_to_uvchr|STRLEN *retlen
465
466Returns the native character value of the first character in the string C<s>
467which is assumed to be in UTF8 encoding; C<retlen> will be set to the
468length, in bytes, of that character.
469
470If C<s> does not point to a well-formed UTF8 character, zero is
471returned and retlen is set, if possible, to -1.
472
473=cut
474*/
475
476UV
477Perl_utf8_to_uvchr(pTHX_ U8* s, STRLEN* retlen)
478{
479 return Perl_utf8n_to_uvchr(aTHX_ s, UTF8_MAXLEN, retlen, 0);
480}
481
482/*
483=for apidoc A|U8* s|utf8_to_uvuni|STRLEN *retlen
484
485Returns the Unicode code point of the first character in the string C<s>
486which is assumed to be in UTF8 encoding; C<retlen> will be set to the
487length, in bytes, of that character.
488
489This function should only be used when returned UV is considered
490an index into the Unicode semantic tables (e.g. swashes).
491
ba210ebe
JH
492If C<s> does not point to a well-formed UTF8 character, zero is
493returned and retlen is set, if possible, to -1.
8e84507e
NIS
494
495=cut
496*/
497
498UV
9041c2e3 499Perl_utf8_to_uvuni(pTHX_ U8* s, STRLEN* retlen)
8e84507e 500{
9041c2e3
NIS
501 /* Call the low level routine asking for checks */
502 return Perl_utf8n_to_uvuni(aTHX_ s, UTF8_MAXLEN, retlen, 0);
8e84507e
NIS
503}
504
b76347f2 505/*
eebe1485 506=for apidoc A|STRLEN|utf8_length|U8* s|U8 *e
b76347f2
JH
507
508Return the length of the UTF-8 char encoded string C<s> in characters.
02eb7b47
JH
509Stops at C<e> (inclusive). If C<e E<lt> s> or if the scan would end
510up past C<e>, croaks.
b76347f2
JH
511
512=cut
513*/
514
515STRLEN
516Perl_utf8_length(pTHX_ U8* s, U8* e)
517{
518 STRLEN len = 0;
519
8850bf83
JH
520 /* Note: cannot use UTF8_IS_...() too eagerly here since e.g.
521 * the bitops (especially ~) can create illegal UTF-8.
522 * In other words: in Perl UTF-8 is not just for Unicode. */
523
b76347f2 524 if (e < s)
02eb7b47 525 Perl_croak(aTHX_ "panic: utf8_length: unexpected end");
b76347f2 526 while (s < e) {
02eb7b47 527 U8 t = UTF8SKIP(s);
b76347f2
JH
528
529 if (e - s < t)
02eb7b47 530 Perl_croak(aTHX_ "panic: utf8_length: unaligned end");
b76347f2
JH
531 s += t;
532 len++;
533 }
534
535 return len;
536}
537
b06226ff 538/*
eebe1485 539=for apidoc A|IV|utf8_distance|U8 *a|U8 *b
b06226ff
JH
540
541Returns the number of UTF8 characters between the UTF-8 pointers C<a>
542and C<b>.
543
544WARNING: use only if you *know* that the pointers point inside the
545same UTF-8 buffer.
546
547=cut */
a0ed51b3 548
02eb7b47 549IV
864dbfa3 550Perl_utf8_distance(pTHX_ U8 *a, U8 *b)
a0ed51b3 551{
02eb7b47
JH
552 IV off = 0;
553
8850bf83
JH
554 /* Note: cannot use UTF8_IS_...() too eagerly here since e.g.
555 * the bitops (especially ~) can create illegal UTF-8.
556 * In other words: in Perl UTF-8 is not just for Unicode. */
557
a0ed51b3
LW
558 if (a < b) {
559 while (a < b) {
02eb7b47
JH
560 U8 c = UTF8SKIP(a);
561
562 if (b - a < c)
563 Perl_croak(aTHX_ "panic: utf8_distance: unaligned end");
564 a += c;
a0ed51b3
LW
565 off--;
566 }
567 }
568 else {
569 while (b < a) {
02eb7b47
JH
570 U8 c = UTF8SKIP(b);
571
572 if (a - b < c)
573 Perl_croak(aTHX_ "panic: utf8_distance: unaligned end");
574 b += c;
a0ed51b3
LW
575 off++;
576 }
577 }
02eb7b47 578
a0ed51b3
LW
579 return off;
580}
581
b06226ff 582/*
eebe1485 583=for apidoc A|U8*|utf8_hop|U8 *s|I32 off
b06226ff 584
8850bf83
JH
585Return the UTF-8 pointer C<s> displaced by C<off> characters, either
586forward or backward.
b06226ff
JH
587
588WARNING: do not use the following unless you *know* C<off> is within
8850bf83
JH
589the UTF-8 data pointed to by C<s> *and* that on entry C<s> is aligned
590on the first byte of character or just after the last byte of a character.
b06226ff
JH
591
592=cut */
a0ed51b3
LW
593
594U8 *
864dbfa3 595Perl_utf8_hop(pTHX_ U8 *s, I32 off)
a0ed51b3 596{
8850bf83
JH
597 /* Note: cannot use UTF8_IS_...() too eagerly here since e.g
598 * the bitops (especially ~) can create illegal UTF-8.
599 * In other words: in Perl UTF-8 is not just for Unicode. */
600
a0ed51b3
LW
601 if (off >= 0) {
602 while (off--)
603 s += UTF8SKIP(s);
604 }
605 else {
606 while (off++) {
607 s--;
8850bf83
JH
608 while (UTF8_IS_CONTINUATION(*s))
609 s--;
a0ed51b3
LW
610 }
611 }
612 return s;
613}
614
6940069f 615/*
eebe1485 616=for apidoc A|U8 *|utf8_to_bytes|U8 *s|STRLEN *len
6940069f 617
246fae53
MG
618Converts a string C<s> of length C<len> from UTF8 into byte encoding.
619Unlike C<bytes_to_utf8>, this over-writes the original string, and
620updates len to contain the new length.
67e989fb 621Returns zero on failure, setting C<len> to -1.
6940069f
GS
622
623=cut
624*/
625
626U8 *
246fae53 627Perl_utf8_to_bytes(pTHX_ U8* s, STRLEN *len)
6940069f 628{
6940069f
GS
629 U8 *send;
630 U8 *d;
dcad2880 631 U8 *save = s;
246fae53
MG
632
633 /* ensure valid UTF8 and chars < 256 before updating string */
dcad2880
JH
634 for (send = s + *len; s < send; ) {
635 U8 c = *s++;
636
9f9ab905 637 if (c >= 0x80 &&
dcad2880
JH
638 ((s >= send) ||
639 ((*s++ & 0xc0) != 0x80) || ((c & 0xfe) != 0xc2))) {
640 *len = -1;
641 return 0;
642 }
246fae53 643 }
dcad2880
JH
644
645 d = s = save;
6940069f 646 while (s < send) {
ed646e6e 647 STRLEN ulen;
9041c2e3 648 *d++ = (U8)utf8_to_uvchr(s, &ulen);
ed646e6e 649 s += ulen;
6940069f
GS
650 }
651 *d = '\0';
246fae53 652 *len = d - save;
6940069f
GS
653 return save;
654}
655
656/*
f9a63242
JH
657=for apidoc A|U8 *|bytes_from_utf8|U8 *s|STRLEN *len|bool *is_utf8
658
659Converts a string C<s> of length C<len> from UTF8 into byte encoding.
660Unlike <utf8_to_bytes> but like C<bytes_to_utf8>, returns a pointer to
ef9edfd0
JH
661the newly-created string, and updates C<len> to contain the new
662length. Returns the original string if no conversion occurs, C<len>
663is unchanged. Do nothing if C<is_utf8> points to 0. Sets C<is_utf8> to
6640 if C<s> is converted or contains all 7bit characters.
f9a63242
JH
665
666=cut */
667
668U8 *
669Perl_bytes_from_utf8(pTHX_ U8* s, STRLEN *len, bool *is_utf8)
670{
671 U8 *send;
672 U8 *d;
673 U8 *start = s;
674 I32 count = 0;
675
676 if (!*is_utf8)
677 return start;
678
ef9edfd0 679 /* ensure valid UTF8 and chars < 256 before converting string */
f9a63242
JH
680 for (send = s + *len; s < send;) {
681 U8 c = *s++;
682 if (!UTF8_IS_ASCII(c)) {
683 if (UTF8_IS_CONTINUATION(c) || s >= send ||
df84a23b 684 !UTF8_IS_CONTINUATION(*s) || UTF8_IS_DOWNGRADEABLE_START(c))
f9a63242
JH
685 return start;
686 s++, count++;
687 }
688 }
689
690 *is_utf8 = 0;
691
692 if (!count)
693 return start;
694
695 Newz(801, d, (*len) - count + 1, U8);
ef9edfd0 696 s = start; start = d;
f9a63242
JH
697 while (s < send) {
698 U8 c = *s++;
90f44359 699
f9a63242
JH
700 if (UTF8_IS_ASCII(c))
701 *d++ = c;
702 else
90f44359 703 *d++ = UTF8_ACCUMULATE(c, *s++);
f9a63242
JH
704 }
705 *d = '\0';
706 *len = d - start;
707 return start;
708}
709
710/*
eebe1485 711=for apidoc A|U8 *|bytes_to_utf8|U8 *s|STRLEN *len
6940069f
GS
712
713Converts a string C<s> of length C<len> from ASCII into UTF8 encoding.
6662521e
GS
714Returns a pointer to the newly-created string, and sets C<len> to
715reflect the new length.
6940069f 716
497711e7 717=cut
6940069f
GS
718*/
719
720U8*
6662521e 721Perl_bytes_to_utf8(pTHX_ U8* s, STRLEN *len)
6940069f 722{
6940069f
GS
723 U8 *send;
724 U8 *d;
725 U8 *dst;
6662521e 726 send = s + (*len);
6940069f 727
6662521e 728 Newz(801, d, (*len) * 2 + 1, U8);
6940069f
GS
729 dst = d;
730
731 while (s < send) {
90f44359 732 if (UTF8_IS_ASCII(*s))
6940069f
GS
733 *d++ = *s++;
734 else {
735 UV uv = *s++;
90f44359
JH
736
737 *d++ = UTF8_EIGHT_BIT_HI(uv);
738 *d++ = UTF8_EIGHT_BIT_LO(uv);
6940069f
GS
739 }
740 }
741 *d = '\0';
6662521e 742 *len = d-dst;
6940069f
GS
743 return dst;
744}
745
a0ed51b3 746/*
dea0fc0b 747 * Convert native (big-endian) or reversed (little-endian) UTF-16 to UTF-8.
a0ed51b3
LW
748 *
749 * Destination must be pre-extended to 3/2 source. Do not use in-place.
750 * We optimize for native, for obvious reasons. */
751
752U8*
dea0fc0b 753Perl_utf16_to_utf8(pTHX_ U8* p, U8* d, I32 bytelen, I32 *newlen)
a0ed51b3 754{
dea0fc0b
JH
755 U8* pend;
756 U8* dstart = d;
757
758 if (bytelen & 1)
a7867d0a 759 Perl_croak(aTHX_ "panic: utf16_to_utf8: odd bytelen");
dea0fc0b
JH
760
761 pend = p + bytelen;
762
a0ed51b3 763 while (p < pend) {
dea0fc0b
JH
764 UV uv = (p[0] << 8) + p[1]; /* UTF-16BE */
765 p += 2;
a0ed51b3
LW
766 if (uv < 0x80) {
767 *d++ = uv;
768 continue;
769 }
770 if (uv < 0x800) {
771 *d++ = (( uv >> 6) | 0xc0);
772 *d++ = (( uv & 0x3f) | 0x80);
773 continue;
774 }
775 if (uv >= 0xd800 && uv < 0xdbff) { /* surrogates */
dea0fc0b
JH
776 UV low = *p++;
777 if (low < 0xdc00 || low >= 0xdfff)
778 Perl_croak(aTHX_ "Malformed UTF-16 surrogate");
a0ed51b3
LW
779 uv = ((uv - 0xd800) << 10) + (low - 0xdc00) + 0x10000;
780 }
781 if (uv < 0x10000) {
782 *d++ = (( uv >> 12) | 0xe0);
783 *d++ = (((uv >> 6) & 0x3f) | 0x80);
784 *d++ = (( uv & 0x3f) | 0x80);
785 continue;
786 }
787 else {
788 *d++ = (( uv >> 18) | 0xf0);
789 *d++ = (((uv >> 12) & 0x3f) | 0x80);
790 *d++ = (((uv >> 6) & 0x3f) | 0x80);
791 *d++ = (( uv & 0x3f) | 0x80);
792 continue;
793 }
794 }
dea0fc0b 795 *newlen = d - dstart;
a0ed51b3
LW
796 return d;
797}
798
799/* Note: this one is slightly destructive of the source. */
800
801U8*
dea0fc0b 802Perl_utf16_to_utf8_reversed(pTHX_ U8* p, U8* d, I32 bytelen, I32 *newlen)
a0ed51b3
LW
803{
804 U8* s = (U8*)p;
805 U8* send = s + bytelen;
806 while (s < send) {
807 U8 tmp = s[0];
808 s[0] = s[1];
809 s[1] = tmp;
810 s += 2;
811 }
dea0fc0b 812 return utf16_to_utf8(p, d, bytelen, newlen);
a0ed51b3
LW
813}
814
815/* for now these are all defined (inefficiently) in terms of the utf8 versions */
816
817bool
864dbfa3 818Perl_is_uni_alnum(pTHX_ U32 c)
a0ed51b3 819{
ad391ad9 820 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 821 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
822 return is_utf8_alnum(tmpbuf);
823}
824
825bool
b8c5462f
JH
826Perl_is_uni_alnumc(pTHX_ U32 c)
827{
ad391ad9 828 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 829 uvuni_to_utf8(tmpbuf, (UV)c);
b8c5462f
JH
830 return is_utf8_alnumc(tmpbuf);
831}
832
833bool
864dbfa3 834Perl_is_uni_idfirst(pTHX_ U32 c)
a0ed51b3 835{
ad391ad9 836 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 837 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
838 return is_utf8_idfirst(tmpbuf);
839}
840
841bool
864dbfa3 842Perl_is_uni_alpha(pTHX_ U32 c)
a0ed51b3 843{
ad391ad9 844 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 845 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
846 return is_utf8_alpha(tmpbuf);
847}
848
849bool
4d61ec05
GS
850Perl_is_uni_ascii(pTHX_ U32 c)
851{
ad391ad9 852 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 853 uvuni_to_utf8(tmpbuf, (UV)c);
4d61ec05
GS
854 return is_utf8_ascii(tmpbuf);
855}
856
857bool
864dbfa3 858Perl_is_uni_space(pTHX_ U32 c)
a0ed51b3 859{
ad391ad9 860 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 861 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
862 return is_utf8_space(tmpbuf);
863}
864
865bool
864dbfa3 866Perl_is_uni_digit(pTHX_ U32 c)
a0ed51b3 867{
ad391ad9 868 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 869 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
870 return is_utf8_digit(tmpbuf);
871}
872
873bool
864dbfa3 874Perl_is_uni_upper(pTHX_ U32 c)
a0ed51b3 875{
ad391ad9 876 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 877 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
878 return is_utf8_upper(tmpbuf);
879}
880
881bool
864dbfa3 882Perl_is_uni_lower(pTHX_ U32 c)
a0ed51b3 883{
ad391ad9 884 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 885 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
886 return is_utf8_lower(tmpbuf);
887}
888
889bool
b8c5462f
JH
890Perl_is_uni_cntrl(pTHX_ U32 c)
891{
ad391ad9 892 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 893 uvuni_to_utf8(tmpbuf, (UV)c);
b8c5462f
JH
894 return is_utf8_cntrl(tmpbuf);
895}
896
897bool
898Perl_is_uni_graph(pTHX_ U32 c)
899{
ad391ad9 900 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 901 uvuni_to_utf8(tmpbuf, (UV)c);
b8c5462f
JH
902 return is_utf8_graph(tmpbuf);
903}
904
905bool
864dbfa3 906Perl_is_uni_print(pTHX_ U32 c)
a0ed51b3 907{
ad391ad9 908 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 909 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
910 return is_utf8_print(tmpbuf);
911}
912
b8c5462f 913bool
f248d071 914Perl_is_uni_punct(pTHX_ U32 c)
b8c5462f 915{
ad391ad9 916 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 917 uvuni_to_utf8(tmpbuf, (UV)c);
b8c5462f
JH
918 return is_utf8_punct(tmpbuf);
919}
920
4d61ec05
GS
921bool
922Perl_is_uni_xdigit(pTHX_ U32 c)
923{
ad391ad9 924 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 925 uvuni_to_utf8(tmpbuf, (UV)c);
4d61ec05
GS
926 return is_utf8_xdigit(tmpbuf);
927}
928
a0ed51b3 929U32
864dbfa3 930Perl_to_uni_upper(pTHX_ U32 c)
a0ed51b3 931{
ad391ad9 932 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 933 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
934 return to_utf8_upper(tmpbuf);
935}
936
937U32
864dbfa3 938Perl_to_uni_title(pTHX_ U32 c)
a0ed51b3 939{
ad391ad9 940 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 941 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
942 return to_utf8_title(tmpbuf);
943}
944
945U32
864dbfa3 946Perl_to_uni_lower(pTHX_ U32 c)
a0ed51b3 947{
ad391ad9 948 U8 tmpbuf[UTF8_MAXLEN+1];
9041c2e3 949 uvuni_to_utf8(tmpbuf, (UV)c);
a0ed51b3
LW
950 return to_utf8_lower(tmpbuf);
951}
952
953/* for now these all assume no locale info available for Unicode > 255 */
954
955bool
864dbfa3 956Perl_is_uni_alnum_lc(pTHX_ U32 c)
a0ed51b3
LW
957{
958 return is_uni_alnum(c); /* XXX no locale support yet */
959}
960
961bool
b8c5462f
JH
962Perl_is_uni_alnumc_lc(pTHX_ U32 c)
963{
964 return is_uni_alnumc(c); /* XXX no locale support yet */
965}
966
967bool
864dbfa3 968Perl_is_uni_idfirst_lc(pTHX_ U32 c)
a0ed51b3
LW
969{
970 return is_uni_idfirst(c); /* XXX no locale support yet */
971}
972
973bool
864dbfa3 974Perl_is_uni_alpha_lc(pTHX_ U32 c)
a0ed51b3
LW
975{
976 return is_uni_alpha(c); /* XXX no locale support yet */
977}
978
979bool
4d61ec05
GS
980Perl_is_uni_ascii_lc(pTHX_ U32 c)
981{
982 return is_uni_ascii(c); /* XXX no locale support yet */
983}
984
985bool
864dbfa3 986Perl_is_uni_space_lc(pTHX_ U32 c)
a0ed51b3
LW
987{
988 return is_uni_space(c); /* XXX no locale support yet */
989}
990
991bool
864dbfa3 992Perl_is_uni_digit_lc(pTHX_ U32 c)
a0ed51b3
LW
993{
994 return is_uni_digit(c); /* XXX no locale support yet */
995}
996
997bool
864dbfa3 998Perl_is_uni_upper_lc(pTHX_ U32 c)
a0ed51b3
LW
999{
1000 return is_uni_upper(c); /* XXX no locale support yet */
1001}
1002
1003bool
864dbfa3 1004Perl_is_uni_lower_lc(pTHX_ U32 c)
a0ed51b3
LW
1005{
1006 return is_uni_lower(c); /* XXX no locale support yet */
1007}
1008
1009bool
b8c5462f
JH
1010Perl_is_uni_cntrl_lc(pTHX_ U32 c)
1011{
1012 return is_uni_cntrl(c); /* XXX no locale support yet */
1013}
1014
1015bool
1016Perl_is_uni_graph_lc(pTHX_ U32 c)
1017{
1018 return is_uni_graph(c); /* XXX no locale support yet */
1019}
1020
1021bool
864dbfa3 1022Perl_is_uni_print_lc(pTHX_ U32 c)
a0ed51b3
LW
1023{
1024 return is_uni_print(c); /* XXX no locale support yet */
1025}
1026
b8c5462f
JH
1027bool
1028Perl_is_uni_punct_lc(pTHX_ U32 c)
1029{
1030 return is_uni_punct(c); /* XXX no locale support yet */
1031}
1032
4d61ec05
GS
1033bool
1034Perl_is_uni_xdigit_lc(pTHX_ U32 c)
1035{
1036 return is_uni_xdigit(c); /* XXX no locale support yet */
1037}
1038
a0ed51b3 1039U32
864dbfa3 1040Perl_to_uni_upper_lc(pTHX_ U32 c)
a0ed51b3
LW
1041{
1042 return to_uni_upper(c); /* XXX no locale support yet */
1043}
1044
1045U32
864dbfa3 1046Perl_to_uni_title_lc(pTHX_ U32 c)
a0ed51b3
LW
1047{
1048 return to_uni_title(c); /* XXX no locale support yet */
1049}
1050
1051U32
864dbfa3 1052Perl_to_uni_lower_lc(pTHX_ U32 c)
a0ed51b3
LW
1053{
1054 return to_uni_lower(c); /* XXX no locale support yet */
1055}
1056
a0ed51b3 1057bool
864dbfa3 1058Perl_is_utf8_alnum(pTHX_ U8 *p)
a0ed51b3 1059{
386d01d6
GS
1060 if (!is_utf8_char(p))
1061 return FALSE;
a0ed51b3 1062 if (!PL_utf8_alnum)
289d4f09
ML
1063 /* NOTE: "IsWord", not "IsAlnum", since Alnum is a true
1064 * descendant of isalnum(3), in other words, it doesn't
1065 * contain the '_'. --jhi */
1066 PL_utf8_alnum = swash_init("utf8", "IsWord", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1067 return swash_fetch(PL_utf8_alnum, p);
1068/* return *p == '_' || is_utf8_alpha(p) || is_utf8_digit(p); */
1069#ifdef SURPRISINGLY_SLOWER /* probably because alpha is usually true */
1070 if (!PL_utf8_alnum)
1071 PL_utf8_alnum = swash_init("utf8", "",
1072 sv_2mortal(newSVpv("+utf8::IsAlpha\n+utf8::IsDigit\n005F\n",0)), 0, 0);
1073 return swash_fetch(PL_utf8_alnum, p);
1074#endif
1075}
1076
1077bool
b8c5462f
JH
1078Perl_is_utf8_alnumc(pTHX_ U8 *p)
1079{
386d01d6
GS
1080 if (!is_utf8_char(p))
1081 return FALSE;
b8c5462f
JH
1082 if (!PL_utf8_alnum)
1083 PL_utf8_alnum = swash_init("utf8", "IsAlnumC", &PL_sv_undef, 0, 0);
1084 return swash_fetch(PL_utf8_alnum, p);
1085/* return is_utf8_alpha(p) || is_utf8_digit(p); */
1086#ifdef SURPRISINGLY_SLOWER /* probably because alpha is usually true */
1087 if (!PL_utf8_alnum)
1088 PL_utf8_alnum = swash_init("utf8", "",
1089 sv_2mortal(newSVpv("+utf8::IsAlpha\n+utf8::IsDigit\n005F\n",0)), 0, 0);
1090 return swash_fetch(PL_utf8_alnum, p);
1091#endif
1092}
1093
1094bool
864dbfa3 1095Perl_is_utf8_idfirst(pTHX_ U8 *p)
a0ed51b3
LW
1096{
1097 return *p == '_' || is_utf8_alpha(p);
1098}
1099
1100bool
864dbfa3 1101Perl_is_utf8_alpha(pTHX_ U8 *p)
a0ed51b3 1102{
386d01d6
GS
1103 if (!is_utf8_char(p))
1104 return FALSE;
a0ed51b3 1105 if (!PL_utf8_alpha)
e24b16f9 1106 PL_utf8_alpha = swash_init("utf8", "IsAlpha", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1107 return swash_fetch(PL_utf8_alpha, p);
1108}
1109
1110bool
b8c5462f
JH
1111Perl_is_utf8_ascii(pTHX_ U8 *p)
1112{
386d01d6
GS
1113 if (!is_utf8_char(p))
1114 return FALSE;
b8c5462f
JH
1115 if (!PL_utf8_ascii)
1116 PL_utf8_ascii = swash_init("utf8", "IsAscii", &PL_sv_undef, 0, 0);
1117 return swash_fetch(PL_utf8_ascii, p);
1118}
1119
1120bool
864dbfa3 1121Perl_is_utf8_space(pTHX_ U8 *p)
a0ed51b3 1122{
386d01d6
GS
1123 if (!is_utf8_char(p))
1124 return FALSE;
a0ed51b3 1125 if (!PL_utf8_space)
3bec3564 1126 PL_utf8_space = swash_init("utf8", "IsSpacePerl", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1127 return swash_fetch(PL_utf8_space, p);
1128}
1129
1130bool
864dbfa3 1131Perl_is_utf8_digit(pTHX_ U8 *p)
a0ed51b3 1132{
386d01d6
GS
1133 if (!is_utf8_char(p))
1134 return FALSE;
a0ed51b3 1135 if (!PL_utf8_digit)
e24b16f9 1136 PL_utf8_digit = swash_init("utf8", "IsDigit", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1137 return swash_fetch(PL_utf8_digit, p);
1138}
1139
1140bool
864dbfa3 1141Perl_is_utf8_upper(pTHX_ U8 *p)
a0ed51b3 1142{
386d01d6
GS
1143 if (!is_utf8_char(p))
1144 return FALSE;
a0ed51b3 1145 if (!PL_utf8_upper)
e24b16f9 1146 PL_utf8_upper = swash_init("utf8", "IsUpper", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1147 return swash_fetch(PL_utf8_upper, p);
1148}
1149
1150bool
864dbfa3 1151Perl_is_utf8_lower(pTHX_ U8 *p)
a0ed51b3 1152{
386d01d6
GS
1153 if (!is_utf8_char(p))
1154 return FALSE;
a0ed51b3 1155 if (!PL_utf8_lower)
e24b16f9 1156 PL_utf8_lower = swash_init("utf8", "IsLower", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1157 return swash_fetch(PL_utf8_lower, p);
1158}
1159
1160bool
b8c5462f
JH
1161Perl_is_utf8_cntrl(pTHX_ U8 *p)
1162{
386d01d6
GS
1163 if (!is_utf8_char(p))
1164 return FALSE;
b8c5462f
JH
1165 if (!PL_utf8_cntrl)
1166 PL_utf8_cntrl = swash_init("utf8", "IsCntrl", &PL_sv_undef, 0, 0);
1167 return swash_fetch(PL_utf8_cntrl, p);
1168}
1169
1170bool
1171Perl_is_utf8_graph(pTHX_ U8 *p)
1172{
386d01d6
GS
1173 if (!is_utf8_char(p))
1174 return FALSE;
b8c5462f
JH
1175 if (!PL_utf8_graph)
1176 PL_utf8_graph = swash_init("utf8", "IsGraph", &PL_sv_undef, 0, 0);
1177 return swash_fetch(PL_utf8_graph, p);
1178}
1179
1180bool
864dbfa3 1181Perl_is_utf8_print(pTHX_ U8 *p)
a0ed51b3 1182{
386d01d6
GS
1183 if (!is_utf8_char(p))
1184 return FALSE;
a0ed51b3 1185 if (!PL_utf8_print)
e24b16f9 1186 PL_utf8_print = swash_init("utf8", "IsPrint", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1187 return swash_fetch(PL_utf8_print, p);
1188}
1189
1190bool
b8c5462f
JH
1191Perl_is_utf8_punct(pTHX_ U8 *p)
1192{
386d01d6
GS
1193 if (!is_utf8_char(p))
1194 return FALSE;
b8c5462f
JH
1195 if (!PL_utf8_punct)
1196 PL_utf8_punct = swash_init("utf8", "IsPunct", &PL_sv_undef, 0, 0);
1197 return swash_fetch(PL_utf8_punct, p);
1198}
1199
1200bool
1201Perl_is_utf8_xdigit(pTHX_ U8 *p)
1202{
386d01d6
GS
1203 if (!is_utf8_char(p))
1204 return FALSE;
b8c5462f
JH
1205 if (!PL_utf8_xdigit)
1206 PL_utf8_xdigit = swash_init("utf8", "IsXDigit", &PL_sv_undef, 0, 0);
1207 return swash_fetch(PL_utf8_xdigit, p);
1208}
1209
1210bool
864dbfa3 1211Perl_is_utf8_mark(pTHX_ U8 *p)
a0ed51b3 1212{
386d01d6
GS
1213 if (!is_utf8_char(p))
1214 return FALSE;
a0ed51b3 1215 if (!PL_utf8_mark)
e24b16f9 1216 PL_utf8_mark = swash_init("utf8", "IsM", &PL_sv_undef, 0, 0);
a0ed51b3
LW
1217 return swash_fetch(PL_utf8_mark, p);
1218}
1219
2104c8d9 1220UV
864dbfa3 1221Perl_to_utf8_upper(pTHX_ U8 *p)
a0ed51b3
LW
1222{
1223 UV uv;
1224
1225 if (!PL_utf8_toupper)
e24b16f9 1226 PL_utf8_toupper = swash_init("utf8", "ToUpper", &PL_sv_undef, 4, 0);
a0ed51b3 1227 uv = swash_fetch(PL_utf8_toupper, p);
9041c2e3 1228 return uv ? UNI_TO_NATIVE(uv) : utf8_to_uvchr(p,0);
a0ed51b3
LW
1229}
1230
2104c8d9 1231UV
864dbfa3 1232Perl_to_utf8_title(pTHX_ U8 *p)
a0ed51b3
LW
1233{
1234 UV uv;
1235
1236 if (!PL_utf8_totitle)
e24b16f9 1237 PL_utf8_totitle = swash_init("utf8", "ToTitle", &PL_sv_undef, 4, 0);
a0ed51b3 1238 uv = swash_fetch(PL_utf8_totitle, p);
9041c2e3 1239 return uv ? UNI_TO_NATIVE(uv) : utf8_to_uvchr(p,0);
a0ed51b3
LW
1240}
1241
2104c8d9 1242UV
864dbfa3 1243Perl_to_utf8_lower(pTHX_ U8 *p)
a0ed51b3
LW
1244{
1245 UV uv;
1246
1247 if (!PL_utf8_tolower)
e24b16f9 1248 PL_utf8_tolower = swash_init("utf8", "ToLower", &PL_sv_undef, 4, 0);
a0ed51b3 1249 uv = swash_fetch(PL_utf8_tolower, p);
9041c2e3 1250 return uv ? UNI_TO_NATIVE(uv) : utf8_to_uvchr(p,0);
a0ed51b3
LW
1251}
1252
1253/* a "swash" is a swatch hash */
1254
1255SV*
864dbfa3 1256Perl_swash_init(pTHX_ char* pkg, char* name, SV *listsv, I32 minbits, I32 none)
a0ed51b3
LW
1257{
1258 SV* retval;
bf1fed83 1259 SV* tokenbufsv = sv_2mortal(NEWSV(0,0));
8e84507e 1260 dSP;
ce3b816e
GS
1261
1262 if (!gv_stashpv(pkg, 0)) { /* demand load utf8 */
1263 ENTER;
1264 Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, newSVpv(pkg,0), Nullsv);
1265 LEAVE;
1266 }
1267 SPAGAIN;
a0ed51b3
LW
1268 PUSHSTACKi(PERLSI_MAGIC);
1269 PUSHMARK(SP);
1270 EXTEND(SP,5);
1271 PUSHs(sv_2mortal(newSVpvn(pkg, strlen(pkg))));
1272 PUSHs(sv_2mortal(newSVpvn(name, strlen(name))));
1273 PUSHs(listsv);
1274 PUSHs(sv_2mortal(newSViv(minbits)));
1275 PUSHs(sv_2mortal(newSViv(none)));
1276 PUTBACK;
1277 ENTER;
1278 SAVEI32(PL_hints);
1279 PL_hints = 0;
1280 save_re_context();
bf1fed83
JH
1281 if (PL_curcop == &PL_compiling)
1282 /* XXX ought to be handled by lex_start */
1283 sv_setpv(tokenbufsv, PL_tokenbuf);
864dbfa3 1284 if (call_method("SWASHNEW", G_SCALAR))
8e84507e 1285 retval = newSVsv(*PL_stack_sp--);
a0ed51b3 1286 else
e24b16f9 1287 retval = &PL_sv_undef;
a0ed51b3
LW
1288 LEAVE;
1289 POPSTACK;
e24b16f9 1290 if (PL_curcop == &PL_compiling) {
bf1fed83
JH
1291 STRLEN len;
1292 char* pv = SvPV(tokenbufsv, len);
1293
1294 Copy(pv, PL_tokenbuf, len+1, char);
e24b16f9 1295 PL_curcop->op_private = PL_hints;
a0ed51b3
LW
1296 }
1297 if (!SvROK(retval) || SvTYPE(SvRV(retval)) != SVt_PVHV)
cea2e8a9 1298 Perl_croak(aTHX_ "SWASHNEW didn't return an HV ref");
a0ed51b3
LW
1299 return retval;
1300}
1301
1302UV
864dbfa3 1303Perl_swash_fetch(pTHX_ SV *sv, U8 *ptr)
a0ed51b3
LW
1304{
1305 HV* hv = (HV*)SvRV(sv);
1306 U32 klen = UTF8SKIP(ptr) - 1;
1307 U32 off = ptr[klen] & 127; /* NB: 64 bit always 0 when len > 1 */
1308 STRLEN slen;
1309 STRLEN needents = (klen ? 64 : 128);
dfe13c55 1310 U8 *tmps;
a0ed51b3
LW
1311 U32 bit;
1312 SV *retval;
1313
1314 /*
1315 * This single-entry cache saves about 1/3 of the utf8 overhead in test
1316 * suite. (That is, only 7-8% overall over just a hash cache. Still,
1317 * it's nothing to sniff at.) Pity we usually come through at least
1318 * two function calls to get here...
1319 *
1320 * NB: this code assumes that swatches are never modified, once generated!
1321 */
1322
1323 if (hv == PL_last_swash_hv &&
1324 klen == PL_last_swash_klen &&
12ae5dfc 1325 (!klen || memEQ((char *)ptr,(char *)PL_last_swash_key,klen)) )
a0ed51b3
LW
1326 {
1327 tmps = PL_last_swash_tmps;
1328 slen = PL_last_swash_slen;
1329 }
1330 else {
1331 /* Try our second-level swatch cache, kept in a hash. */
dfe13c55 1332 SV** svp = hv_fetch(hv, (char*)ptr, klen, FALSE);
a0ed51b3
LW
1333
1334 /* If not cached, generate it via utf8::SWASHGET */
dfe13c55 1335 if (!svp || !SvPOK(*svp) || !(tmps = (U8*)SvPV(*svp, slen))) {
a0ed51b3
LW
1336 dSP;
1337 ENTER;
1338 SAVETMPS;
1339 save_re_context();
1340 PUSHSTACKi(PERLSI_MAGIC);
1341 PUSHMARK(SP);
1342 EXTEND(SP,3);
1343 PUSHs((SV*)sv);
9041c2e3
NIS
1344 /* We call utf8_to_uni as we want and index into Unicode tables,
1345 not a native character number.
1346 */
1347 PUSHs(sv_2mortal(newSViv(utf8_to_uvuni(ptr, 0) & ~(needents - 1))));
a0ed51b3
LW
1348 PUSHs(sv_2mortal(newSViv(needents)));
1349 PUTBACK;
864dbfa3 1350 if (call_method("SWASHGET", G_SCALAR))
8e84507e 1351 retval = newSVsv(*PL_stack_sp--);
a0ed51b3 1352 else
e24b16f9 1353 retval = &PL_sv_undef;
a0ed51b3
LW
1354 POPSTACK;
1355 FREETMPS;
1356 LEAVE;
e24b16f9
GS
1357 if (PL_curcop == &PL_compiling)
1358 PL_curcop->op_private = PL_hints;
a0ed51b3 1359
dfe13c55 1360 svp = hv_store(hv, (char*)ptr, klen, retval, 0);
a0ed51b3 1361
dfe13c55 1362 if (!svp || !(tmps = (U8*)SvPV(*svp, slen)) || slen < 8)
cea2e8a9 1363 Perl_croak(aTHX_ "SWASHGET didn't return result of proper length");
a0ed51b3
LW
1364 }
1365
1366 PL_last_swash_hv = hv;
1367 PL_last_swash_klen = klen;
1368 PL_last_swash_tmps = tmps;
1369 PL_last_swash_slen = slen;
1370 if (klen)
1371 Copy(ptr, PL_last_swash_key, klen, U8);
1372 }
1373
9faf8d75 1374 switch ((int)((slen << 3) / needents)) {
a0ed51b3
LW
1375 case 1:
1376 bit = 1 << (off & 7);
1377 off >>= 3;
1378 return (tmps[off] & bit) != 0;
1379 case 8:
1380 return tmps[off];
1381 case 16:
1382 off <<= 1;
1383 return (tmps[off] << 8) + tmps[off + 1] ;
1384 case 32:
1385 off <<= 2;
1386 return (tmps[off] << 24) + (tmps[off+1] << 16) + (tmps[off+2] << 8) + tmps[off + 3] ;
1387 }
cea2e8a9 1388 Perl_croak(aTHX_ "panic: swash_fetch");
a0ed51b3
LW
1389 return 0;
1390}