1/*
2 * ICU glue
3 */
4
5#include "windlocl.h"
6#include <unicode/usprep.h>
7
8int
9wind_stringprep(const uint32_t *in, size_t in_len,
10		uint32_t *out, size_t *out_len,
11		wind_profile_flags flags)
12{
13    UErrorCode status = 0;
14    UStringPrepProfile *profile;
15    UStringPrepProfileType type;
16    UChar *uin, *dest;
17    int32_t len;
18    size_t n;
19
20    if (in_len > UINT_MAX / sizeof(in[0]) || (*out_len) > UINT_MAX / sizeof(out[0]))
21	return EINVAL;
22
23    if (flags & WIND_PROFILE_SASL)
24	type = USPREP_RFC4013_SASLPREP;
25    else
26	return EINVAL;
27
28    /*
29     * Should cache profile
30     */
31
32    profile = usprep_openByType(type, &status);
33    if (profile == NULL)
34	return ENOENT;
35
36    uin = malloc(in_len * sizeof(uin[0]));
37    dest = malloc(*out_len * sizeof(dest[0]));
38    if (uin == NULL || dest == NULL) {
39	free(uin);
40	free(dest);
41	usprep_close(profile);
42	return ENOMEM;
43    }
44
45    /* ucs42ucs2 - don't care about surogates */
46    for (n = 0; n < in_len; n++)
47	uin[n] = in[n];
48
49    status = 0;
50
51    len = usprep_prepare(profile, uin, (int32_t)in_len, dest, (int32_t)*out_len,
52			 USPREP_DEFAULT, NULL, &status);
53
54    if (len < 0 || status) {
55	free(dest);
56	free(uin);
57	return EINVAL;
58    }
59
60    for (n = 0; n < len; n++)
61	out[n] = dest[n];
62
63    *out_len = len;
64
65    free(dest);
66    free(uin);
67
68    return 0;
69}
70