1 /*
2 LibRCC - module handling internal string representation
3
4 Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License version 2.1 or later
8 as published by the Free Software Foundation.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include <string.h>
24 #ifdef HAVE_STRINGS_H
25 # include <strings.h>
26 #endif /* HAVE_STRINGS_H */
27
28 #include "../config.h"
29
30 #include "internal.h"
31 #include "rccstring.h"
32
rccCreateString(rcc_language_id language_id,const char * buf,size_t len)33 rcc_string rccCreateString(rcc_language_id language_id, const char *buf, size_t len) {
34 char *res;
35 rcc_string_header *header;
36
37 if (!buf) return NULL;
38 if (!len) len = strlen(buf);
39
40 res = (char*)malloc(len+sizeof(rcc_string_header)+1);
41 if (!res) return NULL;
42
43 memcpy(res + sizeof(rcc_string_header), buf, len);
44 res[sizeof(rcc_string_header) + len] = 0;
45
46 memset(res, 0xFF, sizeof(rcc_string_header));
47 header = (rcc_string_header*)res;
48 header->magic = RCC_STRING_MAGIC;
49 header->language_id = language_id;
50
51 return (rcc_string)res;
52 }
53
rccStringSetLang(rcc_string string,const char * sn)54 int rccStringSetLang(rcc_string string, const char *sn) {
55 if ((!string)||(!sn)||(strlen(sn)!=2)) return -1;
56 memcpy(&((rcc_string_header*)string)->language,sn,2);
57 return 0;
58 }
59
rccStringFixID(rcc_string string,rcc_context ctx)60 int rccStringFixID(rcc_string string, rcc_context ctx) {
61 char lang[3];
62 const char *curlang;
63 rcc_language_config config;
64 rcc_language_id language_id;
65 rcc_string_header *header;
66
67 if ((!string)||(!ctx)||(!rccStringCheck(string))) return -1;
68 header = (rcc_string_header*)string;
69
70
71 memcpy(lang, header->language, 2); lang[2] = 0;
72 curlang = rccGetLanguageName(ctx, header->language_id);
73 if ((curlang)&&(!strcasecmp(lang, curlang))) return 0;
74
75 language_id = rccGetLanguageByName(ctx, lang);
76 if ((language_id == (rcc_language_id)-1)||(language_id == 0)) return -1;
77 config = rccGetConfig(ctx, language_id);
78 if (!config) return -1;
79
80 header->language_id = language_id;
81 return 0;
82 }
83
rccStringChangeID(rcc_string string,rcc_language_id language_id)84 int rccStringChangeID(rcc_string string, rcc_language_id language_id) {
85 if ((!string)&&(language_id != (rcc_language_id)-1)) return -1;
86
87 // printf("ChangingID %lu: %s\n", language_id, string);
88 ((rcc_string_header*)string)->language_id = language_id;
89 return 0;
90 }
91
92
rccStringFree(rcc_string str)93 void rccStringFree(rcc_string str) {
94 if (str) free(str);
95 }
96
rccStringCheck(const char * str)97 size_t rccStringCheck(const char *str) {
98 size_t len;
99
100 if (!str) return 0;
101
102 len = strlen(str);
103 if (len>sizeof(rcc_string_header)) {
104 len-=sizeof(rcc_string_header);
105 if (((rcc_string_header*)str)->magic == RCC_STRING_MAGIC) return len;
106 }
107
108 return 0;
109 }
110
rccStringSizedCheck(const char * str,size_t len)111 size_t rccStringSizedCheck(const char *str, size_t len) {
112 size_t newlen;
113
114 if (!str) return 0;
115
116 newlen = len?len:strlen(str);
117 if (newlen>sizeof(rcc_string_header)) {
118 if ((len==newlen)&&(!str[newlen-2])) return 0;
119 newlen-=sizeof(rcc_string_header);
120 } else return 0;
121 if (((rcc_string_header*)str)->magic == RCC_STRING_MAGIC) return newlen;
122 return 0;
123 }
124
125
rccStringGetLanguage(rcc_const_string str)126 rcc_language_id rccStringGetLanguage(rcc_const_string str) {
127 if (!str) return (rcc_language_id)-1;
128 return ((rcc_string_header*)str)->language_id;
129 }
130
rccStringGetString(rcc_const_string str)131 const char *rccStringGetString(rcc_const_string str) {
132 return (const char *)str + sizeof(rcc_string_header);
133 }
134
rccStringExtractString(rcc_const_string str)135 char *rccStringExtractString(rcc_const_string str) {
136 size_t len;
137 char *res;
138
139 len = rccStringCheck(str);
140 if (!len) return NULL;
141
142 res = (char*)malloc(len+1);
143 if (!res) return NULL;
144
145 memcpy(res, rccStringGetString(str), len);
146 res[len] = 0;
147
148 return res;
149 }
150
151
rccGetString(const char * str)152 const char *rccGetString(const char *str) {
153 if (rccStringCheck(str)) return rccStringGetString((const rcc_string)str);
154 return str;
155 }
156
rccSizedGetString(const char * str,size_t len)157 const char *rccSizedGetString(const char *str, size_t len) {
158 size_t newlen;
159
160 newlen = rccStringSizedCheck(str, len);
161 if (newlen) {
162 return rccStringGetString((const rcc_string)str);
163 }
164
165 return (const char *)str;
166 }
167
168
rccStringCmp(const char * str1,const char * str2)169 int rccStringCmp(const char *str1, const char *str2) {
170 return strcmp(rccGetString(str1), rccGetString(str2));
171 }
172
rccStringNCmp(const char * str1,const char * str2,size_t n)173 int rccStringNCmp(const char *str1, const char *str2, size_t n) {
174 return strncmp(rccGetString(str1), rccGetString(str2), n);
175 }
176
rccStringCaseCmp(const char * str1,const char * str2)177 int rccStringCaseCmp(const char *str1, const char *str2) {
178 return strcasecmp(rccGetString(str1), rccGetString(str2));
179 }
180
rccStringNCaseCmp(const char * str1,const char * str2,size_t n)181 int rccStringNCaseCmp(const char *str1, const char *str2, size_t n) {
182 return strncasecmp(rccGetString(str1), rccGetString(str2), n);
183 }
184
185 #ifndef HAVE_STRNLEN
rccStrnlen(const char * str,size_t size)186 int rccStrnlen(const char *str, size_t size) {
187 unsigned int i;
188 for (i=0;((i<size)&&(str[i]));i++);
189 return i;
190 }
191 #endif /* HAVE_STRNLEN */
192
193
rccIsASCII(const char * str)194 int rccIsASCII(const char *str) {
195 unsigned int i;
196
197 for (i=0;str[i];i++)
198 if ((unsigned char)str[i]>0x7F) return 0;
199 return 1;
200 }
201
rccStringSizedGetChars(const char * str,size_t size)202 size_t rccStringSizedGetChars(const char *str, size_t size) {
203 size_t i, skip = 0, chars = 0;
204 const unsigned char *tmp;
205
206 tmp = (unsigned char*)rccGetString(str);
207
208 for (i=0;(size?(size-i):tmp[i]);i++) {
209 if (skip) {
210 skip--;
211 continue;
212 }
213
214 if (tmp[i]<0x80) skip = 0;
215 else if ((tmp[i]>0xBF)&&(tmp[i]<0xE0)) skip = 1;
216 else if ((tmp[i]>0xDF)&&(tmp[i]<0xF0)) skip = 2;
217 else if ((tmp[i]>0xEF)&&(tmp[i]<0xF8)) skip = 3;
218 else skip = 4;
219 chars++;
220 }
221
222 return chars;
223 }
224