Fix index sorting so that it collates in a sensible order.
[sgt/halibut] / ustring.c
1 /*
2 * ustring.c: Unicode string routines
3 */
4
5 #include <wchar.h>
6 #include <time.h>
7 #include "halibut.h"
8
9 wchar_t *ustrdup(wchar_t *s) {
10 wchar_t *r;
11 if (s) {
12 r = mknewa(wchar_t, 1+ustrlen(s));
13 ustrcpy(r, s);
14 } else {
15 r = mknew(wchar_t);
16 *r = 0;
17 }
18 return r;
19 }
20
21 char *ustrtoa(wchar_t *s, char *outbuf, int size) {
22 char *p;
23 if (!s) {
24 *outbuf = '\0';
25 return outbuf;
26 }
27 for (p = outbuf; *s && p < outbuf+size; p++,s++)
28 *p = *s;
29 if (p < outbuf+size)
30 *p = '\0';
31 else
32 outbuf[size-1] = '\0';
33 return outbuf;
34 }
35
36 int ustrlen(wchar_t *s) {
37 int len = 0;
38 while (*s++) len++;
39 return len;
40 }
41
42 wchar_t *uadv(wchar_t *s) {
43 return s + 1 + ustrlen(s);
44 }
45
46 wchar_t *ustrcpy(wchar_t *dest, wchar_t *source) {
47 wchar_t *ret = dest;
48 do {
49 *dest++ = *source;
50 } while (*source++);
51 return ret;
52 }
53
54 int ustrcmp(wchar_t *lhs, wchar_t *rhs) {
55 if (!lhs && !rhs) return 0;
56 if (!lhs) return -1;
57 if (!rhs) return +1;
58 while (*lhs && *rhs && *lhs==*rhs)
59 lhs++, rhs++;
60 if (*lhs < *rhs)
61 return -1;
62 else if (*lhs > *rhs)
63 return 1;
64 return 0;
65 }
66
67 wchar_t utolower(wchar_t c) {
68 if (c == L'\0')
69 return c; /* this property needed by ustricmp */
70 /* FIXME: this doesn't even come close */
71 if (c >= 'A' && c <= 'Z')
72 c += 'a'-'A';
73 return c;
74 }
75
76 int uisalpha(wchar_t c) {
77 /* FIXME: this doesn't even come close */
78 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
79 }
80
81 int ustricmp(wchar_t *lhs, wchar_t *rhs) {
82 wchar_t lc, rc;
83 while ((lc = utolower(*lhs)) == (rc = utolower(*rhs)) && lc && rc)
84 lhs++, rhs++;
85 if (!lc && !rc)
86 return 0;
87 if (lc < rc)
88 return -1;
89 else
90 return 1;
91 }
92
93 wchar_t *ustrlow(wchar_t *s) {
94 wchar_t *p = s;
95 while (*p) {
96 *p = utolower(*p);
97 p++;
98 }
99 return s;
100 }
101
102 int utoi(wchar_t *s) {
103 int sign = +1;
104 int n;
105
106 if (*s == L'-') {
107 s++;
108 sign = -1;
109 }
110
111 n = 0;
112 while (*s && *s >= L'0' && *s <= L'9') {
113 n *= 10;
114 n += (*s - '0');
115 s++;
116 }
117
118 return n;
119 }
120
121 int utob(wchar_t *s) {
122 if (!ustricmp(s, L"yes") || !ustricmp(s, L"y") ||
123 !ustricmp(s, L"true") || !ustricmp(s, L"t"))
124 return TRUE;
125 return FALSE;
126 }
127
128 int uisdigit(wchar_t c) {
129 return c >= L'0' && c <= L'9';
130 }
131
132 #define USTRFTIME_DELTA 128
133 wchar_t *ustrftime(wchar_t *wfmt, struct tm *timespec) {
134 void *blk = NULL;
135 wchar_t *wblk, *wp;
136 char *fmt, *text, *p;
137 size_t size = 0;
138 size_t len;
139
140 /*
141 * strftime has the entertaining property that it returns 0
142 * _either_ on out-of-space _or_ on successful generation of
143 * the empty string. Hence we must ensure our format can never
144 * generate the empty string. Somebody throw a custard pie at
145 * whoever was responsible for that. Please?
146 */
147 if (wfmt) {
148 len = ustrlen(wfmt);
149 fmt = mknewa(char, 2+len);
150 ustrtoa(wfmt, fmt+1, len+1);
151 fmt[0] = ' ';
152 } else
153 fmt = " %c";
154
155 while (1) {
156 size += USTRFTIME_DELTA;
157 blk = resize((char *)blk, size);
158 len = strftime((char *)blk, size-1, fmt, timespec);
159 if (len > 0)
160 break;
161 }
162
163 /* Note: +1 for the terminating 0, -1 for the initial space in fmt */
164 wblk = resize((wchar_t *)blk, len);
165 text = mknewa(char, len);
166 strftime(text, len, fmt+1, timespec);
167 /*
168 * We operate in the C locale, so this all ought to be kosher
169 * ASCII. If we ever move outside ASCII machines, we may need
170 * to make this more portable...
171 */
172 for (wp = wblk, p = text; *p; p++, wp++)
173 *wp = *p;
174 *wp = 0;
175 if (wfmt)
176 sfree(fmt);
177 sfree(text);
178 return wblk;
179 }