Ahem; let's have all the man page headings at the same level!
[sgt/halibut] / ustring.c
CommitLineData
d7482997 1/*
2 * ustring.c: Unicode string routines
3 */
4
5#include <wchar.h>
6#include <time.h>
7#include "halibut.h"
8
9wchar_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
21char *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
ba9c1487 36wchar_t *ustrfroma(char *s, wchar_t *outbuf, int size) {
37 wchar_t *p;
38 if (!s) {
39 *outbuf = L'\0';
40 return outbuf;
41 }
42 for (p = outbuf; *s && p < outbuf+size; p++,s++)
43 *p = *s;
44 if (p < outbuf+size)
45 *p = '\0';
46 else
47 outbuf[size-1] = '\0';
48 return outbuf;
49}
50
50d6b4bd 51char *utoa_dup(wchar_t *s) {
52 int len;
53 char *buf = NULL;
54
55 len = ustrlen(s) + 1;
56 do {
57 buf = resize(buf, len);
58 ustrtoa(s, buf, len);
59 len = (3 * len) / 2 + 1; /* this guarantees a strict increase */
60 } while ((int)strlen(buf) >= len-1);
61
62 buf = resize(buf, strlen(buf)+1);
63 return buf;
64}
65
ba9c1487 66wchar_t *ufroma_dup(char *s) {
67 int len;
68 wchar_t *buf = NULL;
69
70 len = strlen(s) + 1;
71 do {
72 buf = resize(buf, len);
73 ustrfroma(s, buf, len);
74 len = (3 * len) / 2 + 1; /* this guarantees a strict increase */
75 } while (ustrlen(buf) >= len-1);
76
77 buf = resize(buf, ustrlen(buf)+1);
78 return buf;
79}
80
d7482997 81int ustrlen(wchar_t *s) {
82 int len = 0;
83 while (*s++) len++;
84 return len;
85}
86
87wchar_t *uadv(wchar_t *s) {
88 return s + 1 + ustrlen(s);
89}
90
91wchar_t *ustrcpy(wchar_t *dest, wchar_t *source) {
92 wchar_t *ret = dest;
93 do {
94 *dest++ = *source;
95 } while (*source++);
96 return ret;
97}
98
99int ustrcmp(wchar_t *lhs, wchar_t *rhs) {
100 if (!lhs && !rhs) return 0;
101 if (!lhs) return -1;
102 if (!rhs) return +1;
103 while (*lhs && *rhs && *lhs==*rhs)
104 lhs++, rhs++;
105 if (*lhs < *rhs)
106 return -1;
107 else if (*lhs > *rhs)
108 return 1;
109 return 0;
110}
111
112wchar_t utolower(wchar_t c) {
113 if (c == L'\0')
114 return c; /* this property needed by ustricmp */
115 /* FIXME: this doesn't even come close */
116 if (c >= 'A' && c <= 'Z')
117 c += 'a'-'A';
118 return c;
119}
120
831da32e 121int uisalpha(wchar_t c) {
122 /* FIXME: this doesn't even come close */
123 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
124}
125
d7482997 126int ustricmp(wchar_t *lhs, wchar_t *rhs) {
127 wchar_t lc, rc;
128 while ((lc = utolower(*lhs)) == (rc = utolower(*rhs)) && lc && rc)
129 lhs++, rhs++;
130 if (!lc && !rc)
131 return 0;
132 if (lc < rc)
133 return -1;
134 else
135 return 1;
136}
137
138wchar_t *ustrlow(wchar_t *s) {
139 wchar_t *p = s;
140 while (*p) {
141 *p = utolower(*p);
142 p++;
143 }
144 return s;
145}
146
147int utoi(wchar_t *s) {
148 int sign = +1;
149 int n;
150
151 if (*s == L'-') {
152 s++;
153 sign = -1;
154 }
155
156 n = 0;
157 while (*s && *s >= L'0' && *s <= L'9') {
158 n *= 10;
159 n += (*s - '0');
160 s++;
161 }
162
163 return n;
164}
165
166int utob(wchar_t *s) {
167 if (!ustricmp(s, L"yes") || !ustricmp(s, L"y") ||
168 !ustricmp(s, L"true") || !ustricmp(s, L"t"))
169 return TRUE;
170 return FALSE;
171}
172
173int uisdigit(wchar_t c) {
174 return c >= L'0' && c <= L'9';
175}
176
177#define USTRFTIME_DELTA 128
178wchar_t *ustrftime(wchar_t *wfmt, struct tm *timespec) {
179 void *blk = NULL;
180 wchar_t *wblk, *wp;
181 char *fmt, *text, *p;
182 size_t size = 0;
183 size_t len;
184
185 /*
186 * strftime has the entertaining property that it returns 0
187 * _either_ on out-of-space _or_ on successful generation of
188 * the empty string. Hence we must ensure our format can never
189 * generate the empty string. Somebody throw a custard pie at
190 * whoever was responsible for that. Please?
191 */
192 if (wfmt) {
193 len = ustrlen(wfmt);
194 fmt = mknewa(char, 2+len);
195 ustrtoa(wfmt, fmt+1, len+1);
196 fmt[0] = ' ';
197 } else
198 fmt = " %c";
199
200 while (1) {
201 size += USTRFTIME_DELTA;
202 blk = resize((char *)blk, size);
203 len = strftime((char *)blk, size-1, fmt, timespec);
204 if (len > 0)
205 break;
206 }
207
208 /* Note: +1 for the terminating 0, -1 for the initial space in fmt */
209 wblk = resize((wchar_t *)blk, len);
210 text = mknewa(char, len);
211 strftime(text, len, fmt+1, timespec);
212 /*
213 * We operate in the C locale, so this all ought to be kosher
214 * ASCII. If we ever move outside ASCII machines, we may need
215 * to make this more portable...
216 */
217 for (wp = wblk, p = text; *p; p++, wp++)
218 *wp = *p;
219 *wp = 0;
220 if (wfmt)
221 sfree(fmt);
222 sfree(text);
223 return wblk;
224}