summaryrefslogtreecommitdiff
path: root/ustring.c
blob: 86f013a9cae60f2ec1891038d3c73733ec6bc43a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
 * ustring.c: Unicode string routines
 */

#include <wchar.h>
#include <time.h>
#include "buttress.h"

wchar_t *ustrdup(wchar_t *s) {
    wchar_t *r;
    if (s) {
	r = smalloc((1+ustrlen(s)) * sizeof(wchar_t));
	ustrcpy(r, s);
    } else {
	r = smalloc(1);
	*r = 0;
    }
    return r;
}

char *ustrtoa(wchar_t *s, char *outbuf, int size) {
    char *p;
    if (!s) {
	*outbuf = '\0';
	return outbuf;
    }
    for (p = outbuf; *s && p < outbuf+size; p++,s++)
	*p = *s;
    if (p < outbuf+size)
	*p = '\0';
    else
	outbuf[size-1] = '\0';
    return outbuf;
}

int ustrlen(wchar_t *s) {
    int len = 0;
    while (*s++) len++;
    return len;
}

wchar_t *ustrcpy(wchar_t *dest, wchar_t *source) {
    wchar_t *ret = dest;
    do {
	*dest++ = *source;
    } while (*source++);
    return ret;
}

int ustrcmp(wchar_t *lhs, wchar_t *rhs) {
    while (*lhs && *rhs && *lhs==*rhs)
	lhs++, rhs++;
    if (*lhs < *rhs)
	return -1;
    else if (*lhs > *rhs)
	return 1;
    return 0;
}

wchar_t *ustrlow(wchar_t *s) {
    wchar_t *p = s;
    while (*p) {
	/* FIXME: this doesn't even come close */
	if (*p >= 'A' && *p <= 'Z')
	    *p += 'a'-'A';
	p++;
    }
    return s;
}

#define USTRFTIME_DELTA 128
wchar_t *ustrftime(wchar_t *wfmt, struct tm *timespec) {
    void *blk = NULL;
    wchar_t *wblk, *wp;
    char *fmt, *text, *p;
    size_t size = 0;
    size_t len;

    /*
     * strftime has the entertaining property that it returns 0
     * _either_ on out-of-space _or_ on successful generation of
     * the empty string. Hence we must ensure our format can never
     * generate the empty string. Somebody throw a custard pie at
     * whoever was responsible for that. Please?
     */
    if (wfmt) {
	len = ustrlen(wfmt);
	fmt = smalloc(2+len);
	ustrtoa(wfmt, fmt+1, len+1);
	fmt[0] = ' ';
    } else
	fmt = " %c";

    while (1) {
	size += USTRFTIME_DELTA;
	blk = srealloc(blk, size);
	len = strftime((char *)blk, size-1, fmt, timespec);
	if (len > 0)
	    break;
    }

    /* Note: +1 for the terminating 0, -1 for the initial space in fmt */
    wblk = srealloc(blk, len * sizeof(wchar_t));
    text = smalloc(len);
    strftime(text, len, fmt+1, timespec);
    /*
     * We operate in the C locale, so this all ought to be kosher
     * ASCII. If we ever move outside ASCII machines, we may need
     * to make this more portable...
     */
    for (wp = wblk, p = text; *p; p++, wp++)
	*wp = *p;
    *wp = 0;
    if (wfmt)
	sfree(fmt);
    sfree(text);
    return wblk;
}