z_HTTP_header_add_basic_auth uses z_HTTP_header_set
[yaz-moved-to-github.git] / src / icu_utf8.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file
8  * \brief UTF-8 string utilities for ICU
9  */
10
11 #if HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #if YAZ_HAVE_ICU
16 #include <yaz/xmalloc.h>
17
18 #include <yaz/icu_I18N.h>
19
20 #include <yaz/log.h>
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include <unicode/ustring.h>  /* some more string fcns*/
27 #include <unicode/uchar.h>    /* char names           */
28
29 struct icu_buf_utf8 *icu_buf_utf8_create(size_t capacity)
30 {
31     struct icu_buf_utf8 *buf8
32         = (struct icu_buf_utf8 *) xmalloc(sizeof(struct icu_buf_utf8));
33
34     buf8->utf8_len = 0;
35     buf8->utf8_cap = capacity;
36     if (capacity > 0)
37     {
38         buf8->utf8 = (uint8_t *) xmalloc(sizeof(uint8_t) * capacity);
39         buf8->utf8[0] = (uint8_t) 0;
40     }
41     else
42         buf8->utf8 = 0;
43     return buf8;
44 }
45
46 struct icu_buf_utf8 *icu_buf_utf8_clear(struct icu_buf_utf8 *buf8)
47 {
48     if (buf8)
49     {
50         if (buf8->utf8)
51             buf8->utf8[0] = (uint8_t) 0;
52         buf8->utf8_len = 0;
53     }
54     return buf8;
55 }
56
57 struct icu_buf_utf8 *icu_buf_utf8_resize(struct icu_buf_utf8 *buf8,
58                                          size_t capacity)
59 {
60     if (!buf8)
61         return 0;
62
63     if (capacity > 0)
64     {
65         if (0 == buf8->utf8)
66             buf8->utf8 = (uint8_t *) xmalloc(sizeof(uint8_t) * capacity);
67         else
68             buf8->utf8
69                 = (uint8_t *) xrealloc(buf8->utf8, sizeof(uint8_t) * capacity);
70
71         buf8->utf8_cap = capacity;
72     }
73     else
74     {
75         xfree(buf8->utf8);
76         buf8->utf8 = 0;
77         buf8->utf8_cap = 0;
78     }
79
80     return buf8;
81 }
82
83 const char *icu_buf_utf8_to_cstr(struct icu_buf_utf8 *src8)
84 {
85     if (!src8 || src8->utf8_len == 0)
86         return "";
87
88     if (src8->utf8_len == src8->utf8_cap)
89         src8 = icu_buf_utf8_resize(src8, src8->utf8_len * 2 + 1);
90
91     src8->utf8[src8->utf8_len] = '\0';
92
93     return (const char *) src8->utf8;
94 }
95
96 void icu_buf_utf8_destroy(struct icu_buf_utf8 *buf8)
97 {
98     if (buf8)
99         xfree(buf8->utf8);
100     xfree(buf8);
101 }
102
103 UErrorCode icu_utf16_from_utf8_cstr(struct icu_buf_utf16 *dest16,
104                                     const char *src8cstr,
105                                     UErrorCode *status)
106 {
107     size_t src8cstr_len = 0;
108     int32_t utf16_len = 0;
109
110     *status = U_ZERO_ERROR;
111     src8cstr_len = strlen(src8cstr);
112
113     u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
114                   &utf16_len,
115                   src8cstr, src8cstr_len, status);
116
117     /* check for buffer overflow, resize and retry */
118     if (*status == U_BUFFER_OVERFLOW_ERROR)
119     {
120         icu_buf_utf16_resize(dest16, utf16_len * 2);
121         *status = U_ZERO_ERROR;
122         u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
123                       &utf16_len,
124                       src8cstr, src8cstr_len, status);
125     }
126
127     if (U_SUCCESS(*status) && utf16_len <= dest16->utf16_cap)
128         dest16->utf16_len = utf16_len;
129     else
130         icu_buf_utf16_clear(dest16);
131
132     return *status;
133 }
134
135 UErrorCode icu_utf16_to_utf8(struct icu_buf_utf8 *dest8,
136                              const struct icu_buf_utf16 *src16,
137                              UErrorCode *status)
138 {
139     int32_t utf8_len = 0;
140
141     u_strToUTF8((char *) dest8->utf8, dest8->utf8_cap,
142                 &utf8_len,
143                 src16->utf16, src16->utf16_len, status);
144
145     /* check for buffer overflow, resize and retry */
146     if (*status == U_BUFFER_OVERFLOW_ERROR)
147     {
148         icu_buf_utf8_resize(dest8, utf8_len * 2);
149         *status = U_ZERO_ERROR;
150         u_strToUTF8((char *) dest8->utf8, dest8->utf8_cap,
151                     &utf8_len,
152                     src16->utf16, src16->utf16_len, status);
153     }
154
155     if (U_SUCCESS(*status) && utf8_len <= dest8->utf8_cap)
156         dest8->utf8_len = utf8_len;
157     else
158         icu_buf_utf8_clear(dest8);
159
160     return *status;
161 }
162
163 #endif /* YAZ_HAVE_ICU */
164
165 /*
166  * Local variables:
167  * c-basic-offset: 4
168  * c-file-style: "Stroustrup"
169  * indent-tabs-mode: nil
170  * End:
171  * vim: shiftwidth=4 tabstop=8 expandtab
172  */
173