revert breaks some stupid old compilers
[oscam.git] / oscam-string.c
blobb7eee6ba162b54d17385320b03e907b37db11ba6
1 #include "globals.h"
2 #include "oscam-string.h"
4 /* This function encapsulates malloc. It automatically adds an error message
5 to the log if it failed and calls cs_exit(quiterror) if quiterror > -1.
6 result will be automatically filled with the new memory position or NULL
7 on failure. */
8 bool cs_malloc(void *result, size_t size)
10 void **tmp = result;
11 *tmp = malloc(size);
12 if(*tmp == NULL)
14 fprintf(stderr, "%s: ERROR: Can't allocate %zu bytes!", __func__, size);
16 else
18 memset(*tmp, 0, size);
20 return !!*tmp;
23 /* This function encapsulates realloc. It automatically adds an error message
24 to the log if it failed and calls cs_exit(quiterror) if quiterror > -1.
25 result will be automatically filled with the new memory position or NULL
26 on failure. If a failure occured, the existing memory in result will
27 be freed. */
28 bool cs_realloc(void *result, size_t size)
30 void **tmp = result, **tmp2 = result;
31 *tmp = realloc(*tmp, size);
32 if(*tmp == NULL)
34 fprintf(stderr, "%s: ERROR: Can't allocate %zu bytes!", __func__, size);
35 NULLFREE(*tmp2);
37 return !!*tmp;
40 /* Allocates a new empty string and copies str into it. You need to free() the result. */
41 char *cs_strdup(const char *str)
43 char *newstr;
44 if(!str)
45 { return NULL; }
46 if(cs_malloc(&newstr, strlen(str) + 1))
48 strncpy(newstr, str, strlen(str));
49 return newstr;
51 return NULL;
54 /* Ordinary strncpy does not terminate the string if the source is exactly
55 as long or longer as the specified size. This can raise security issues.
56 This function is a replacement which makes sure that a \0 is always added.
57 num should be the real size of char array (do not subtract -1). */
58 void cs_strncpy(char *destination, const char *source, size_t num)
60 if(!source)
62 destination[0] = '\0';
63 return;
65 uint32_t l, size = strlen(source);
66 if(size > num - 1)
67 { l = num - 1; }
68 else
69 { l = size; }
70 memcpy(destination, source, l);
71 destination[l] = '\0';
74 /* Converts the string txt to it's lower case representation. */
75 char *strtolower(char *txt)
77 char *p;
78 for(p = txt; *p; p++)
80 if(isupper((uchar)*p))
81 { *p = tolower((uchar) * p); }
83 return txt;
86 /* Converts the string txt to it's upper case representation. */
87 char *strtoupper(char *txt)
89 char *p;
90 for(p = txt; *p; p++)
92 if(islower((uchar)*p))
93 { *p = toupper((uchar) * p); }
95 return txt;
98 char *trim(char *txt)
100 int32_t l;
101 char *p1, *p2;
102 if(*txt == ' ')
104 for(p1 = p2 = txt; (*p1 == ' ') || (*p1 == '\t') || (*p1 == '\n') || (*p1 == '\r'); p1++)
105 { ; }
106 while(*p1)
107 { *p2++ = *p1++; }
108 *p2 = '\0';
110 l = strlen(txt);
111 if(l > 0)
113 for(p1 = txt + l - 1; l > 0 && ((*p1 == ' ') || (*p1 == '\t') || (*p1 == '\n') || (*p1 == '\r')); *p1-- = '\0', l--)
114 { ; }
116 return txt;
119 char *trim2(char *txt)
121 int32_t i, n;
123 for(i=n=0; i<(int32_t)strlen(txt); i++)
125 if(txt[i] == ' ' || txt[i] == '\t') continue;
126 if(txt[i] == '#') {break;}
127 txt[n] = txt[i];
128 n++;
130 txt[n] = '\0';
132 return txt;
135 char *remove_white_chars(char *txt)
138 char *p1 = txt, *p2 = txt;
140 if(NULL != p1)
142 while('\0' != *p1)
144 if((' ' != *p1) && ('\t' != *p1) &&
145 ('\n' != *p1) && ('\r' != *p1))
147 *p2++ = *p1;
149 p1++;
151 *p2 = '\0';
153 return txt;
156 bool streq(const char *s1, const char *s2)
158 if(!s1 && s2) { return 0; }
159 if(s1 && !s2) { return 0; }
160 if(!s1 && !s2) { return 1; }
161 return strcmp(s1, s2) == 0;
164 char *cs_hexdump(int32_t m, const uchar *buf, int32_t n, char *target, int32_t len)
166 int32_t i = 0;
167 target[0] = '\0';
168 m = m ? 3 : 2;
169 if(m * n >= len)
170 { n = (len / m) - 1; }
171 while(i < n)
173 snprintf(target + (m * i), len - (m * i), "%02X%s", *buf++, m > 2 ? " " : "");
174 i++;
176 return target;
179 int32_t gethexval(char c)
181 if(c >= '0' && c <= '9') { return c - '0'; }
182 if(c >= 'A' && c <= 'F') { return c - 'A' + 10; }
183 if(c >= 'a' && c <= 'f') { return c - 'a' + 10; }
184 return -1;
187 int32_t cs_atob(uchar *buf, char *asc, int32_t n)
189 int32_t i, rc;
190 for(i = 0; i < n; i++)
192 rc = (gethexval(asc[i << 1]) << 4) | gethexval(asc[(i << 1) + 1]);
193 if(rc & 0x100)
194 { return -1; }
195 buf[i] = rc;
197 return n;
200 uint32_t cs_atoi(char *asc, int32_t l, int32_t val_on_err)
202 int32_t i, n = 0;
203 uint32_t rc = 0;
204 for(i = ((l - 1) << 1), errno = 0; i >= 0 && n < 4; i -= 2)
206 int32_t b = (gethexval(asc[i]) << 4) | gethexval(asc[i + 1]);
207 if(b < 0)
209 errno = EINVAL;
210 rc = val_on_err ? 0xFFFFFFFF : 0;
211 break;
213 rc |= b << (n << 3);
214 n++;
216 return rc;
219 int32_t byte_atob(char *asc)
221 int32_t rc;
222 if(strlen(trim(asc)) != 2)
224 rc = -1;
226 else
228 rc = (gethexval(asc[0]) << 4) | gethexval(asc[1]);
229 if(rc & 0x100)
230 { rc = -1; }
232 return rc;
235 int32_t word_atob(char *asc)
237 int32_t rc;
238 if(strlen(trim(asc)) != 4)
240 rc = -1;
242 else
244 rc = gethexval(asc[0]) << 12 | gethexval(asc[1]) << 8 |
245 gethexval(asc[2]) << 4 | gethexval(asc[3]);
246 if(rc & 0x10000)
247 { rc = -1; }
249 return rc;
253 * dynamic word_atob
254 * converts an 1-6 digit asc hexstring
256 int32_t dyn_word_atob(char *asc)
258 int32_t rc = (-1);
259 int32_t i, len = strlen(trim(asc));
260 if(len <= 6 && len > 0)
262 for(i = 0, rc = 0; i < len; i++)
264 rc = rc << 4 | gethexval(asc[i]);
266 if(rc & 0x1000000)
267 { rc = -1; }
269 return rc;
272 int32_t key_atob_l(char *asc, uchar *bin, int32_t l)
274 int32_t i, n1, n2, rc;
275 for(i = rc = 0; i < l; i += 2)
277 if((n1 = gethexval(asc[i ])) < 0) { rc = -1; }
278 if((n2 = gethexval(asc[i + 1])) < 0) { rc = -1; }
279 bin[i >> 1] = (n1 << 4) + (n2 & 0xff);
281 return rc;
284 uint32_t b2i(int32_t n, const uchar *b)
286 switch(n)
288 case 2:
289 return (b[0] << 8) | b[1];
290 case 3:
291 return (b[0] << 16) | (b[1] << 8) | b[2];
292 case 4:
293 return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]) & 0xffffffffL;
294 default:
295 cs_log("Error in b2i, n=%i", n);
297 return 0;
300 uint64_t b2ll(int32_t n, uchar *b)
302 int32_t i;
303 uint64_t k = 0;
304 for(i = 0; i < n; k += b[i++])
305 { k <<= 8; }
306 return k;
309 uchar *i2b_buf(int32_t n, uint32_t i, uchar *b)
311 switch(n)
313 case 2:
314 b[0] = (i >> 8) & 0xff;
315 b[1] = (i) & 0xff;
316 break;
317 case 3:
318 b[0] = (i >> 16) & 0xff;
319 b[1] = (i >> 8) & 0xff;
320 b[2] = (i) & 0xff;
321 case 4:
322 b[0] = (i >> 24) & 0xff;
323 b[1] = (i >> 16) & 0xff;
324 b[2] = (i >> 8) & 0xff;
325 b[3] = (i) & 0xff;
326 break;
328 return b;
331 void ull2b_buf(uint64_t i, uchar *b)
333 b[0] = (i >> 56) & 0xff;
334 b[1] = (i >> 48) & 0xff;
335 b[2] = (i >> 40) & 0xff;
336 b[3] = (i >> 32) & 0xff;
337 b[4] = (i >> 24) & 0xff;
338 b[5] = (i >> 16) & 0xff;
339 b[6] = (i >> 8) & 0xff;
340 b[7] = (i) & 0xff;
343 uint32_t a2i(char *asc, int32_t bytes)
345 int32_t i, n;
346 uint32_t rc;
347 for(rc = i = 0, n = strlen(trim(asc)) - 1; i < abs(bytes) << 1; n--, i++)
349 if(n >= 0)
351 int32_t rcl;
352 if((rcl = gethexval(asc[n])) < 0)
354 errno = EINVAL;
355 return 0x1f1f1f;
357 rc |= rcl << (i << 2);
359 else
361 if(bytes < 0)
362 { rc |= 0xf << (i << 2); }
365 errno = 0;
366 return rc;
369 int32_t boundary(int32_t exp, int32_t n)
371 return (((n - 1) >> exp) + 1) << exp;
374 /* Checks whether an array has at least one non-zero byte.
375 length specifies the maximum length to check for. */
376 int32_t array_has_nonzero_byte(uchar *value, int32_t length)
378 if(!value)
379 { return 0; }
381 int32_t i;
382 for(i = 0; i < length; i++)
384 if(value[i] > 0)
386 return 1;
389 return 0;
392 #define RAND_POOL_SIZE 64
394 // The last bytes are used to init random seed
395 static uint8_t rand_pool[RAND_POOL_SIZE + sizeof(uint32_t)];
397 void get_random_bytes_init(void)
399 srand(time(NULL));
400 int fd = open("/dev/urandom", O_RDONLY);
401 if(fd < 0)
403 fd = open("/dev/random", O_RDONLY);
404 if(fd < 0)
405 { return; }
407 if(read(fd, rand_pool, RAND_POOL_SIZE + sizeof(uint32_t)) > -1)
409 uint32_t pool_seed = b2i(4, rand_pool + RAND_POOL_SIZE);
410 srand(pool_seed);
412 close(fd);
415 void get_random_bytes(uint8_t *dst, uint32_t dst_len)
417 static uint32_t rand_pool_pos; // *MUST* be static
418 uint32_t i;
419 for(i = 0; i < dst_len; i++)
421 rand_pool_pos++; // Races are welcome...
422 dst[i] = rand() ^ rand_pool[rand_pool_pos % RAND_POOL_SIZE];
426 static uint32_t crc_table[256] =
428 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
429 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
430 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
431 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
432 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
433 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
434 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
435 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
436 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
437 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
438 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
439 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
440 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
441 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
442 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
443 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
444 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
445 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
446 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
447 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
448 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
449 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
450 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
451 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
452 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
453 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
454 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
455 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
456 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
457 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
458 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
459 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
460 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
461 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
462 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
463 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
464 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
465 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
466 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
467 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
468 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
469 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
470 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
471 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
472 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
473 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
474 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
475 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
476 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
477 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
478 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
479 0x2d02ef8dL
483 * crc32 -- compute the CRC-32 of a data stream
484 * Copyright (C) 1995-1996 Mark Adler
485 * For conditions of distribution and use, see copyright notice in zlib.h
487 #define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
488 #define DO2(buf) DO1(buf); DO1(buf);
489 #define DO4(buf) DO2(buf); DO2(buf);
490 #define DO8(buf) DO4(buf); DO4(buf);
492 uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len)
494 if(!buf)
495 { return 0L; }
496 crc = crc ^ 0xffffffffL;
497 while(len >= 8)
499 DO8(buf);
500 len -= 8;
502 if(len)
506 DO1(buf);
508 while(--len);
510 return crc ^ 0xffffffffL;
513 static uint16_t ccitt_crc_table [256] =
515 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5,
516 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,
517 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210,
518 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
519 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c,
520 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
521 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
522 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
523 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6,
524 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
525 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5,
526 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
527 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969,
528 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
529 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
530 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
531 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03,
532 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
533 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6,
534 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
535 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
536 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,
537 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1,
538 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
539 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c,
540 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
541 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb,
542 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
543 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447,
544 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
545 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2,
546 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
547 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9,
548 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,
549 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c,
550 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
551 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0,
552 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,
553 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
554 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
555 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba,
556 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
557 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
560 uint16_t ccitt_crc(uint8_t *data, size_t length, uint16_t seed, uint16_t final)
562 size_t count;
563 uint32_t crc = seed;
564 uint32_t temp;
566 for (count = 0; count < length; ++count)
568 temp = (*data++ ^ (crc >> 8)) & 0xff;
569 crc = ccitt_crc_table[temp] ^ (crc << 8);
571 return (uint16_t)(crc ^ final);
574 // https://en.wikipedia.org/wiki/Jenkins_hash_function
575 uint32_t jhash(const char *key, size_t len)
577 uint32_t hash, i;
578 for(hash = i = 0; i < len; i++)
580 hash += key[i];
581 hash += (hash << 10);
582 hash ^= (hash >> 6);
584 hash += (hash << 3);
585 hash ^= (hash >> 11);
586 hash += (hash << 15);
587 return hash;
590 /* Converts a char to it's hex representation. See char_to_hex on how to use it. */
591 char to_hex(char code)
593 static const char hex[] = "0123456789abcdef";
594 return hex[(int)code & 15];
597 /* Converts a char array to a char array with hex values (needed for example for md5).
598 Note that result needs to be at least (p_array_len * 2) + 1 large. */
599 void char_to_hex(const unsigned char *p_array, uint32_t p_array_len, unsigned char *result)
601 result[p_array_len * 2] = '\0';
602 const unsigned char *p_end = p_array + p_array_len;
603 uint32_t pos = 0;
604 const unsigned char *p;
605 for(p = p_array; p != p_end; p++, pos += 2)
607 result[pos ] = to_hex(*p >> 4);
608 result[pos + 1] = to_hex(*p & 15);
612 static inline unsigned char to_uchar(char ch)
614 return ch;
617 void base64_encode(const char *in, size_t inlen, char *out, size_t outlen)
619 static const char b64str[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
620 while(inlen && outlen)
622 *out++ = b64str[(to_uchar(in[0]) >> 2) & 0x3f];
623 if(!--outlen) { break; }
624 *out++ = b64str[((to_uchar(in[0]) << 4) + (--inlen ? to_uchar(in[1]) >> 4 : 0)) & 0x3f];
625 if(!--outlen) { break; }
626 *out++ = (inlen ? b64str[((to_uchar(in[1]) << 2) + (--inlen ? to_uchar(in[2]) >> 6 : 0)) & 0x3f] : '=');
627 if(!--outlen) { break; }
628 *out++ = inlen ? b64str[to_uchar(in[2]) & 0x3f] : '=';
629 if(!--outlen) { break; }
630 if(inlen) { inlen--; }
631 if(inlen) { in += 3; }
632 if(outlen) { *out = '\0'; }
636 size_t b64encode(const char *in, size_t inlen, char **out)
638 size_t outlen = 1 + BASE64_LENGTH(inlen);
639 if(inlen > outlen)
641 *out = NULL;
642 return 0;
644 if(!cs_malloc(out, outlen))
645 { return -1; }
646 base64_encode(in, inlen, *out, outlen);
647 return outlen - 1;
650 static int8_t b64decoder[256];
652 /* Prepares the base64 decoding array */
653 void b64prepare(void)
655 const unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
656 int32_t i;
657 for(i = sizeof(b64decoder) - 1; i >= 0; --i)
659 b64decoder[i] = -1;
662 for(i = sizeof(alphabet) - 1; i >= 0; --i)
664 b64decoder[alphabet[i]] = i;
668 /* Decodes a base64-encoded string. The given array will be used directly for output and is thus modified! */
669 int32_t b64decode(unsigned char *result)
671 int32_t i, len = strlen((char *)result), j = 0, bits = 0, char_count = 0;
673 if(!b64decoder[0]) { b64prepare(); }
675 for(i = 0; i < len; ++i)
677 if(result[i] == '=') { break; }
678 int8_t tmp = b64decoder[result[i]];
679 if(tmp == -1) { continue; }
680 bits += tmp;
681 ++char_count;
682 if(char_count == 4)
684 result[j++] = bits >> 16;
685 result[j++] = (bits >> 8) & 0xff;
686 result[j++] = bits & 0xff;
687 bits = 0;
688 char_count = 0;
690 else
692 bits <<= 6;
695 if(i == len)
697 if(char_count)
699 result[j] = '\0';
700 return 0;
703 else
705 switch(char_count)
707 case 1:
708 result[j] = '\0';
709 return 0;
710 case 2:
711 result[j++] = bits >> 10;
712 result[j] = '\0';
713 break;
714 case 3:
715 result[j++] = bits >> 16;
716 result[j++] = (bits >> 8) & 0xff;
717 result[j] = '\0';
718 break;
721 return j;
725 #ifdef READ_SDT_CHARSETS
727 // ISO_6937 function taken from VLC
728 /*****************************************************************************
729 * Local conversion routine from ISO_6937 to UTF-8 charset. Support for this
730 * is still missing in libiconv, hence multiple operating systems lack it.
731 * The conversion table adds Euro sign (0xA4) as per ETSI EN 300 468 Annex A
732 *****************************************************************************/
734 static const uint16_t iso_6937_to_ucs4[128] =
736 /* 0x80 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
737 /* 0x88 */ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
738 /* 0x90 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
739 /* 0x98 */ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
740 /* 0xa0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0000, 0x00a7,
741 /* 0xa8 */ 0x00a4, 0x2018, 0x201c, 0x00ab, 0x2190, 0x2191, 0x2192, 0x2193,
742 /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00d7, 0x00b5, 0x00b6, 0x00b7,
743 /* 0xb8 */ 0x00f7, 0x2019, 0x201d, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
744 /* 0xc0 */ 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
745 /* 0xc8 */ 0xffff, 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff,
746 /* 0xd0 */ 0x2014, 0x00b9, 0x00ae, 0x00a9, 0x2122, 0x266a, 0x00ac, 0x00a6,
747 /* 0xd8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e,
748 /* 0xe0 */ 0x2126, 0x00c6, 0x00d0, 0x00aa, 0x0126, 0x0000, 0x0132, 0x013f,
749 /* 0xe8 */ 0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166, 0x014a, 0x0149,
750 /* 0xf0 */ 0x0138, 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0140,
751 /* 0xf8 */ 0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b, 0x00ad
754 /* The outer array range runs from 0xc1 to 0xcf, the inner range from 0x40
755 to 0x7f. */
756 static const uint16_t iso_6937_to_ucs4_comb[15][64] =
758 /* 0xc1 */
760 /* 0x40 */ 0x0000, 0x00c0, 0x0000, 0x0000, 0x0000, 0x00c8, 0x0000, 0x0000,
761 /* 0x48 */ 0x0000, 0x00cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d2,
762 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d9, 0x0000, 0x0000,
763 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
764 /* 0x60 */ 0x0000, 0x00e0, 0x0000, 0x0000, 0x0000, 0x00e8, 0x0000, 0x0000,
765 /* 0x68 */ 0x0000, 0x00ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f2,
766 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f9, 0x0000, 0x0000,
767 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
769 /* 0xc2 */
771 /* 0x40 */ 0x0000, 0x00c1, 0x0000, 0x0106, 0x0000, 0x00c9, 0x0000, 0x0000,
772 /* 0x48 */ 0x0000, 0x00cd, 0x0000, 0x0000, 0x0139, 0x0000, 0x0143, 0x00d3,
773 /* 0x50 */ 0x0000, 0x0000, 0x0154, 0x015a, 0x0000, 0x00da, 0x0000, 0x0000,
774 /* 0x58 */ 0x0000, 0x00dd, 0x0179, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
775 /* 0x60 */ 0x0000, 0x00e1, 0x0000, 0x0107, 0x0000, 0x00e9, 0x0000, 0x0000,
776 /* 0x68 */ 0x0000, 0x00ed, 0x0000, 0x0000, 0x013a, 0x0000, 0x0144, 0x00f3,
777 /* 0x70 */ 0x0000, 0x0000, 0x0155, 0x015b, 0x0000, 0x00fa, 0x0000, 0x0000,
778 /* 0x78 */ 0x0000, 0x00fd, 0x017a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
780 /* 0xc3 */
782 /* 0x40 */ 0x0000, 0x00c2, 0x0000, 0x0108, 0x0000, 0x00ca, 0x0000, 0x011c,
783 /* 0x48 */ 0x0124, 0x00ce, 0x0134, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d4,
784 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x015c, 0x0000, 0x00db, 0x0000, 0x0174,
785 /* 0x58 */ 0x0000, 0x0176, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
786 /* 0x60 */ 0x0000, 0x00e2, 0x0000, 0x0109, 0x0000, 0x00ea, 0x0000, 0x011d,
787 /* 0x68 */ 0x0125, 0x00ee, 0x0135, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f4,
788 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x015d, 0x0000, 0x00fb, 0x0000, 0x0175,
789 /* 0x78 */ 0x0000, 0x0177, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
791 /* 0xc4 */
793 /* 0x40 */ 0x0000, 0x00c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
794 /* 0x48 */ 0x0000, 0x0128, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d1, 0x00d5,
795 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0168, 0x0000, 0x0000,
796 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
797 /* 0x60 */ 0x0000, 0x00e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
798 /* 0x68 */ 0x0000, 0x0129, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f1, 0x00f5,
799 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0169, 0x0000, 0x0000,
800 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
802 /* 0xc5 */
804 /* 0x40 */ 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0112, 0x0000, 0x0000,
805 /* 0x48 */ 0x0000, 0x012a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x014c,
806 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016a, 0x0000, 0x0000,
807 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
808 /* 0x60 */ 0x0000, 0x0101, 0x0000, 0x0000, 0x0000, 0x0113, 0x0000, 0x0000,
809 /* 0x68 */ 0x0000, 0x012b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x014d,
810 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016b, 0x0000, 0x0000,
811 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
813 /* 0xc6 */
815 /* 0x40 */ 0x0000, 0x0102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x011e,
816 /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
817 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x0000, 0x0000,
818 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
819 /* 0x60 */ 0x0000, 0x0103, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x011f,
820 /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
821 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x0000, 0x0000,
822 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
824 /* 0xc7 */
826 /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x010a, 0x0000, 0x0116, 0x0000, 0x0120,
827 /* 0x48 */ 0x0000, 0x0130, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
828 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
829 /* 0x58 */ 0x0000, 0x0000, 0x017b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830 /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x010b, 0x0000, 0x0117, 0x0000, 0x0121,
831 /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
832 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833 /* 0x78 */ 0x0000, 0x0000, 0x017c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
835 /* 0xc8 */
837 /* 0x40 */ 0x0000, 0x00c4, 0x0000, 0x0000, 0x0000, 0x00cb, 0x0000, 0x0000,
838 /* 0x48 */ 0x0000, 0x00cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d6,
839 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00dc, 0x0000, 0x0000,
840 /* 0x58 */ 0x0000, 0x0178, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841 /* 0x60 */ 0x0000, 0x00e4, 0x0000, 0x0000, 0x0000, 0x00eb, 0x0000, 0x0000,
842 /* 0x68 */ 0x0000, 0x00ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f6,
843 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00fc, 0x0000, 0x0000,
844 /* 0x78 */ 0x0000, 0x00ff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
846 /* 0xc9 */
848 0x0000,
850 /* 0xca */
852 /* 0x40 */ 0x0000, 0x00c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
853 /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
854 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016e, 0x0000, 0x0000,
855 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
856 /* 0x60 */ 0x0000, 0x00e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
857 /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
858 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016f, 0x0000, 0x0000,
859 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
861 /* 0xcb */
863 /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x00c7, 0x0000, 0x0000, 0x0000, 0x0122,
864 /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0136, 0x013b, 0x0000, 0x0145, 0x0000,
865 /* 0x50 */ 0x0000, 0x0000, 0x0156, 0x015e, 0x0162, 0x0000, 0x0000, 0x0000,
866 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
867 /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x00e7, 0x0000, 0x0000, 0x0000, 0x0123,
868 /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0137, 0x013c, 0x0000, 0x0146, 0x0000,
869 /* 0x70 */ 0x0000, 0x0000, 0x0157, 0x015f, 0x0163, 0x0000, 0x0000, 0x0000,
870 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
872 /* 0xcc */
874 0x0000,
876 /* 0xcd */
878 /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
879 /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0150,
880 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0170, 0x0000, 0x0000,
881 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
882 /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
883 /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0151,
884 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0171, 0x0000, 0x0000,
885 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
887 /* 0xce */
889 /* 0x40 */ 0x0000, 0x0104, 0x0000, 0x0000, 0x0000, 0x0118, 0x0000, 0x0000,
890 /* 0x48 */ 0x0000, 0x012e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
891 /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0172, 0x0000, 0x0000,
892 /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
893 /* 0x60 */ 0x0000, 0x0105, 0x0000, 0x0000, 0x0000, 0x0119, 0x0000, 0x0000,
894 /* 0x68 */ 0x0000, 0x012f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
895 /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0173, 0x0000, 0x0000,
896 /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
898 /* 0xcf */
900 /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x010c, 0x010e, 0x011a, 0x0000, 0x0000,
901 /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x013d, 0x0000, 0x0147, 0x0000,
902 /* 0x50 */ 0x0000, 0x0000, 0x0158, 0x0160, 0x0164, 0x0000, 0x0000, 0x0000,
903 /* 0x58 */ 0x0000, 0x0000, 0x017d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
904 /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x010d, 0x010f, 0x011b, 0x0000, 0x0000,
905 /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x013e, 0x0000, 0x0148, 0x0000,
906 /* 0x70 */ 0x0000, 0x0000, 0x0159, 0x0161, 0x0165, 0x0000, 0x0000, 0x0000,
907 /* 0x78 */ 0x0000, 0x0000, 0x017e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
911 size_t ISO6937toUTF8( const unsigned char **inbuf, size_t *inbytesleft,
912 unsigned char **outbuf, size_t *outbytesleft )
916 if( !inbuf || !(*inbuf) )
917 return (size_t)(0); /* Reset state requested */
919 const unsigned char *iptr = *inbuf;
920 const unsigned char *iend = iptr + *inbytesleft;
921 unsigned char *optr = *outbuf;
922 unsigned char *oend = optr + *outbytesleft;
923 uint16_t ch;
924 int err = 0;
926 while ( iptr < iend )
928 if( *iptr < 0x80 )
930 if( optr >= oend )
932 err = E2BIG;
933 break; /* No space in outbuf */
935 *optr++ = *iptr++;
936 continue;
940 if ( optr + 2 >= oend )
942 err = E2BIG;
943 break; /* No space in outbuf for multibyte char */
946 ch = iso_6937_to_ucs4[*iptr - 0x80];
948 if( ch == 0xffff )
950 /* Composed character */
951 if ( iptr + 1 >= iend )
953 err = EINVAL;
954 break; /* No next character */
956 if ( iptr[1] < 0x40 || iptr[1] >= 0x80 ||
957 !(ch = iso_6937_to_ucs4_comb[iptr[0] - 0xc1][iptr[1] - 0x40]) )
959 err = EILSEQ;
960 break; /* Illegal combination */
962 iptr += 2;
965 else
967 if ( !ch )
969 err = EILSEQ;
970 break;
972 iptr++;
975 if ( ch < 0x800 )
977 optr[1] = 0x80 | (ch & 0x3f);
978 optr[0] = 0xc0 | (ch >> 6);
979 optr +=2;
981 else
983 optr[2] = 0x80 | (ch & 0x3f);
984 ch >>= 6;
985 optr[1] = 0x80 | (ch & 0x3f);
986 optr[0] = 0xe0 | (ch >> 6);
987 optr += 3;
991 *inbuf = iptr;
992 *outbuf = optr;
993 *inbytesleft = iend - iptr;
994 *outbytesleft = oend - optr;
996 if( err )
998 errno = err;
999 return (size_t)(-1);
1002 return (size_t)(0);
1006 #include "oscam-string-isotables.h"
1008 static const uint16_t *get_iso8859_table(int8_t iso_table_number)
1010 if(iso_table_number > 1 && iso_table_number < 17 && iso_table_number != 12)
1012 if(iso_table_number < 12)
1013 { return iso_8859_to_unicode[iso_table_number - 2]; }
1014 else
1015 { return iso_8859_to_unicode[iso_table_number - 3]; }
1018 else
1019 { return NULL; }
1022 size_t ISO8859toUTF8(int8_t iso_table_number, const unsigned char **inbuf, size_t *inbytesleft,
1023 unsigned char **outbuf, size_t *outbytesleft )
1027 if( !inbuf || !(*inbuf) )
1028 return (size_t)(0); /* Reset state requested */
1030 const unsigned char *iptr = *inbuf;
1031 const unsigned char *iend = iptr + *inbytesleft;
1032 unsigned char *optr = *outbuf;
1033 unsigned char *oend = optr + *outbytesleft;
1034 uint16_t ch;
1035 int err = 0;
1036 const uint16_t *iso_table = NULL;
1038 if( iso_table_number != 1 )
1040 iso_table = get_iso8859_table(iso_table_number);
1041 if ( iso_table == NULL )
1043 errno = EINVAL;
1044 return (size_t)(-1);
1048 while ( iptr < iend )
1050 if( *iptr < 0x80 )
1052 if( optr >= oend )
1054 err = E2BIG;
1055 break; /* No space in outbuf */
1057 *optr++ = *iptr++;
1058 continue;
1061 if( iso_table_number == 1 || *iptr < 0xA1 )
1063 ch = *iptr;
1065 else
1067 ch = iso_table[*iptr - 0xA1];
1070 iptr++;
1072 if ( ch < 0x80 )
1074 if ( optr >= oend )
1076 err = E2BIG;
1077 break; /* No space in outbuf for char */
1080 optr[0] = ch & 0xff;
1081 optr += 1;
1083 else if ( ch < 0x800 )
1085 if ( optr + 1 >= oend )
1087 err = E2BIG;
1088 break; /* No space in outbuf for multibyte char */
1091 optr[1] = 0x80 | (ch & 0x3f);
1092 optr[0] = 0xc0 | (ch >> 6);
1093 optr += 2;
1095 else
1097 if ( optr + 2 >= oend )
1099 err = E2BIG;
1100 break; /* No space in outbuf for multibyte char */
1103 optr[2] = 0x80 | (ch & 0x3f);
1104 ch >>= 6;
1105 optr[1] = 0x80 | (ch & 0x3f);
1106 optr[0] = 0xe0 | (ch >> 6);
1107 optr += 3;
1111 *inbuf = iptr;
1112 *outbuf = optr;
1113 *inbytesleft = iend - iptr;
1114 *outbytesleft = oend - optr;
1116 if( err )
1118 errno = err;
1119 return (size_t)(-1);
1122 return (size_t)(0);
1126 #endif
1128 size_t UnicodetoUTF8(const unsigned char **inbuf, size_t *inbytesleft, unsigned char **outbuf, size_t *outbytesleft)
1130 if( !inbuf || !(*inbuf) )
1131 return (size_t)(0); /* Reset state requested */
1133 const unsigned char *iptr = *inbuf;
1134 const unsigned char *iend = iptr + *inbytesleft;
1135 unsigned char *optr = *outbuf;
1136 unsigned char *oend = optr + *outbytesleft;
1137 uint16_t ch;
1138 int err = 0;
1140 while ( iptr+1 < iend )
1142 ch = (iptr[0] << 8) | iptr[1];
1144 iptr += 2;
1146 if ( ch < 0x80 )
1148 if ( optr >= oend )
1150 err = E2BIG;
1151 break; /* No space in outbuf for char */
1154 optr[0] = ch & 0xff;
1155 optr += 1;
1157 else if ( ch < 0x800 )
1159 if ( optr + 1 >= oend )
1161 err = E2BIG;
1162 break; /* No space in outbuf for multibyte char */
1165 optr[1] = 0x80 | (ch & 0x3f);
1166 optr[0] = 0xc0 | (ch >> 6);
1167 optr += 2;
1169 else
1171 if ( optr + 2 >= oend )
1173 err = E2BIG;
1174 break; /* No space in outbuf for multibyte char */
1177 optr[2] = 0x80 | (ch & 0x3f);
1178 ch >>= 6;
1179 optr[1] = 0x80 | (ch & 0x3f);
1180 optr[0] = 0xe0 | (ch >> 6);
1181 optr += 3;
1185 *inbuf = iptr;
1186 *outbuf = optr;
1187 *inbytesleft = iend - iptr;
1188 *outbytesleft = oend - optr;
1190 if( err )
1192 errno = err;
1193 return (size_t)(-1);
1196 return (size_t)(0);