]> git.saurik.com Git - apple/libc.git/blob - string/FreeBSD/strxfrm.c.patch
Libc-763.13.tar.gz
[apple/libc.git] / string / FreeBSD / strxfrm.c.patch
1 --- strxfrm.c.bsdnew 2009-11-18 18:24:38.000000000 -0800
2 +++ strxfrm.c 2009-11-18 18:38:07.000000000 -0800
3 @@ -28,46 +28,118 @@
4 #include <sys/cdefs.h>
5 __FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.17 2008/10/19 09:10:44 delphij Exp $");
6
7 +#include "xlocale_private.h"
8 +
9 #include <stdlib.h>
10 #include <string.h>
11 +#include <wchar.h>
12 +#include <errno.h>
13 #include "collate.h"
14
15 +/*
16 + * In the non-POSIX case, we transform each character into a string of
17 + * characters representing the character's priority. Since char is usually
18 + * signed, we are limited by 7 bits per byte. To avoid zero, we need to add
19 + * XFRM_OFFSET, so we can't use a full 7 bits. For simplicity, we choose 6
20 + * bits per byte. We choose 4 bytes per character as a good compromise
21 + * between maximum coverage and minimum size. This gives 24 bits, or 16M
22 + * priorities. So we choose COLLATE_MAX_PRIORITY to be (2^24 - 1). This
23 + * this can be increased if more is needed.
24 + */
25 +
26 +#define XFRM_BYTES 4
27 +#define XFRM_OFFSET ('0') /* make all printable characters */
28 +#define XFRM_SHIFT 6
29 +#define XFRM_MASK ((1 << XFRM_SHIFT) - 1)
30 +
31 +static void
32 +xfrm(unsigned char *p, int pri)
33 +{
34 +
35 + p[3] = (pri & XFRM_MASK) + XFRM_OFFSET;
36 + pri >>= XFRM_SHIFT;
37 + p[2] = (pri & XFRM_MASK) + XFRM_OFFSET;
38 + pri >>= XFRM_SHIFT;
39 + p[1] = (pri & XFRM_MASK) + XFRM_OFFSET;
40 + pri >>= XFRM_SHIFT;
41 + p[0] = (pri & XFRM_MASK) + XFRM_OFFSET;
42 +}
43 +
44 size_t
45 -strxfrm(char * __restrict dest, const char * __restrict src, size_t len)
46 +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len,
47 + locale_t loc)
48 {
49 - int prim, sec, l;
50 size_t slen;
51 - char *s, *ss;
52 + wchar_t *wcs, *xf[2];
53 + int sverrno;
54
55 - if (!*src) {
56 + if (!*src && dest) {
57 if (len > 0)
58 *dest = '\0';
59 return 0;
60 }
61
62 - if (__collate_load_error)
63 + NORMALIZE_LOCALE(loc);
64 + if (loc->__collate_load_error || (wcs = __collate_mbstowcs(src, loc)) == NULL)
65 return strlcpy(dest, src, len);
66
67 - slen = 0;
68 - prim = sec = 0;
69 - ss = s = __collate_substitute(src);
70 - while (*s) {
71 - while (*s && !prim) {
72 - __collate_lookup(s, &l, &prim, &sec);
73 - s += l;
74 + __collate_xfrm(wcs, xf, loc);
75 +
76 + slen = wcslen(xf[0]) * XFRM_BYTES;
77 + if (xf[1])
78 + slen += (wcslen(xf[1]) + 1) * XFRM_BYTES;
79 + if (len > 0) {
80 + wchar_t *w = xf[0];
81 + int b = 0;
82 + unsigned char buf[XFRM_BYTES];
83 + unsigned char *bp;
84 + while (len > 1) {
85 + if (!b) {
86 + if (!*w)
87 + break;
88 + xfrm(bp = buf, *w++);
89 + b = XFRM_BYTES;
90 + }
91 + *dest++ = *(char *)bp++;
92 + b--;
93 + len--;
94 }
95 - if (prim) {
96 - if (len > 1) {
97 - *dest++ = (char)prim;
98 + if ((w = xf[1]) != NULL) {
99 + xfrm(bp = buf, 0);
100 + b = XFRM_BYTES;
101 + while (len > 1) {
102 + if (!b)
103 + break;
104 + *dest++ = *(char *)bp++;
105 + b--;
106 + len--;
107 + }
108 + b = 0;
109 + while (len > 1) {
110 + if (!b) {
111 + if (!*w)
112 + break;
113 + xfrm(bp = buf, *w++);
114 + b = XFRM_BYTES;
115 + }
116 + *dest++ = *(char *)bp++;
117 + b--;
118 len--;
119 }
120 - slen++;
121 - prim = 0;
122 }
123 - }
124 - free(ss);
125 - if (len > 0)
126 - *dest = '\0';
127 + *dest = 0;
128 + }
129 + sverrno = errno;
130 + free(wcs);
131 + free(xf[0]);
132 + free(xf[1]);
133 + errno = sverrno;
134
135 return slen;
136 }
137 +
138 +size_t
139 +strxfrm(char * __restrict dest, const char * __restrict src, size_t len)
140 +{
141 + return strxfrm_l(dest, src, len, __current_locale());
142 +}