Fix search bug.
[doldaconnect.git] / lib / utils.c
1 /*
2  *  Dolda Connect - Modular multiuser Direct Connect-style client
3  *  Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
4  *  
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *  
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *  
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <malloc.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <wchar.h>
24 #include <iconv.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <wctype.h>
28 #include <langinfo.h>
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 #include <doldaconnect/utils.h>
34
35 extern int vswprintf (wchar_t *__restrict __s, size_t __n,
36                       __const wchar_t *__restrict __format,
37                       __gnuc_va_list __arg);
38
39 char *vsprintf2(char *format, va_list al)
40 {
41     int ret;
42     char *buf;
43     
44     ret = vsnprintf(NULL, 0, format, al);
45     if((buf = malloc(ret + 1)) == NULL)
46     {
47         return(NULL);
48     }
49     vsnprintf(buf, ret + 1, format, al);
50     return(buf);
51 }
52
53 char *sprintf2(char *format, ...)
54 {
55     va_list args;
56     char *buf;
57     
58     va_start(args, format);
59     buf = vsprintf2(format, args);
60     va_end(args);
61     return(buf);
62 }
63
64 wchar_t *vswprintf2(wchar_t *format, va_list al)
65 {
66     int ret;
67     wchar_t *buf;
68     size_t bufsize;
69     
70     buf = smalloc(sizeof(wchar_t) * (bufsize = 1024));
71     while((ret = vswprintf(buf, bufsize, format, al)) < 0)
72         buf = srealloc(buf, sizeof(wchar_t) * (bufsize *= 2));
73     if(bufsize > ret + 1)
74         buf = srealloc(buf, sizeof(wchar_t) * (ret + 1));
75     return(buf);
76 }
77
78 wchar_t *swprintf2(wchar_t *format, ...)
79 {
80     va_list args;
81     wchar_t *buf;
82     
83     va_start(args, format);
84     buf = vswprintf2(format, args);
85     va_end(args);
86     return(buf);
87 }
88
89 wchar_t *icmbstowcs(char *mbs, char *charset)
90 {
91     int ret;
92     char *buf;
93     char *p, *p2;
94     size_t len1, len2, bufsize, data;
95     iconv_t cd;
96     
97     len1 = strlen(mbs) + 1;
98     bufsize = len2 = len1 * sizeof(wchar_t);
99     if((buf = malloc(bufsize)) == NULL)
100     {
101         return(NULL);
102     }
103     if(charset == NULL)
104         charset = nl_langinfo(CODESET);
105     if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
106     {
107         free(buf);
108         return(NULL);
109     }
110     p = buf;
111     while(len1 > 0)
112     {
113         ret = iconv(cd, &mbs, &len1, &p, &len2);
114         if(ret < 0)
115         {
116             if(errno == E2BIG)
117             {
118                 data = p - buf;
119                 len2 += 128;
120                 bufsize += 128;
121                 if((p2 = realloc(buf, bufsize)) == NULL)
122                 {
123                     free(buf);
124                     return(NULL);
125                 }
126                 buf = p2;
127                 p = buf + data;
128             } else {
129                 free(buf);
130                 return(NULL);
131             }
132         }
133     }
134     if(len2 > 0)
135         buf = realloc(buf, p - buf);
136     iconv_close(cd);
137     return((wchar_t *)buf);
138 }
139
140 wchar_t *icsmbstowcs(char *mbs, char *charset, wchar_t *def)
141 {
142     static wchar_t *buf = NULL;
143     
144     if(buf != NULL)
145         free(buf);
146     if((buf = icmbstowcs(mbs, charset)) == NULL)
147         return(def);
148     return(buf);
149 }
150
151 char *icwcstombs(wchar_t *wcs, char *charset)
152 {
153     int ret;
154     char *buf;
155     char *p, *p2;
156     size_t len1, len2, bufsize, data;
157     iconv_t cd;
158     
159     len1 = sizeof(wchar_t) * (wcslen(wcs) + 1);
160     bufsize = len2 = len1;
161     if((buf = malloc(bufsize)) == NULL)
162     {
163         return(NULL);
164     }
165     if(charset == NULL)
166         charset = nl_langinfo(CODESET);
167     if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
168     {
169         free(buf);
170         return(NULL);
171     }
172     p = buf;
173     while(len1 > 0)
174     {
175         ret = iconv(cd, (char **)&wcs, &len1, &p, &len2);
176         if(ret < 0)
177         {
178             if(errno == E2BIG)
179             {
180                 data = p - buf;
181                 len2 += 128;
182                 bufsize += 128;
183                 if((p2 = realloc(buf, bufsize)) == NULL)
184                 {
185                     free(buf);
186                     return(NULL);
187                 }
188                 buf = p2;
189                 p = buf + data;
190             } else {
191                 free(buf);
192                 return(NULL);
193             }
194         }
195     }
196     if(len2 > 0)
197         buf = realloc(buf, p - buf);
198     iconv_close(cd);
199     return(buf);
200 }
201
202 char *icswcstombs(wchar_t *wcs, char *charset, char *def)
203 {
204     static char *buf = NULL;
205     
206     if(buf != NULL)
207         free(buf);
208     if((buf = icwcstombs(wcs, charset)) == NULL)
209         return(def);
210     return(buf);
211 }
212
213 wchar_t *wcstolower(wchar_t *wcs)
214 {
215     wchar_t *p;
216     
217     for(p = wcs; *p != L'\0'; p++)
218         *p = towlower(*p);
219     return(wcs);
220 }
221
222 void _sizebuf(void **buf, size_t *bufsize, size_t reqsize, size_t elsize, int algo)
223 {
224     if(*bufsize >= reqsize)
225         return;
226     switch(algo)
227     {
228     case 0:
229         *buf = srealloc(*buf, elsize * ((*bufsize) = reqsize));
230         break;
231     case 1:
232         if(*bufsize == 0)
233             *bufsize = 1;
234         while(*bufsize < reqsize)
235             *bufsize *= 2;
236         *buf = srealloc(*buf, elsize * (*bufsize));
237         break;
238     }
239 }