/fluffos/fliconv.c
https://github.com/quixadhal/bloodlines · C · 210 lines · 182 code · 28 blank · 0 comment · 31 complexity · 53418ae7778f57054b26638794d7c42c MD5 · raw file
- #include "fliconv.h"
- #include <errno.h>
- #include "std.h"
- #include "lpc_incl.h"
- #include "comm.h"
- #ifdef USE_ICONV
- struct translation *head;
- static struct translation *find_translator(const char *encoding){
- struct translation *cur = head;
- while(cur){
- if(!strcmp(cur->name, encoding))
- break;
- cur = cur->next;
- }
- return cur;
- }
- struct translation *get_translator(const char *encoding){
- struct translation *ret = find_translator(encoding);
- if(ret)
- return ret;
- ret = (struct translation *)MALLOC(sizeof(struct translation));
- char *name = (char *)MALLOC(strlen(encoding)+18+1);
- strcpy(name, encoding);
- #ifdef linux
- strcat(name, "//TRANSLIT//IGNORE");
- #endif
- ret->name = name;
- ret->incoming = iconv_open("UTF-8", encoding);
- ret->outgoing = iconv_open(name, "UTF-8");
- ret->next = 0;
- if(ret->incoming == (iconv_t)-1 || ret->outgoing == (iconv_t)-1){
- FREE(name);
- FREE(ret);
- return 0;
- }
- name[strlen(encoding)] = 0;
- if(!head)
- head = ret;
- else {
- struct translation *cur = head;
- while(cur->next)
- cur = cur->next;
- cur->next = ret;
- }
- return ret;
- }
- char *translate(iconv_t tr, const char *mes, int inlen, int *outlen){
- size_t len = inlen;
- size_t len2;
- unsigned char *tmp = (unsigned char *)mes;
- static char *res = 0;
- static size_t reslen = 0;
- char *tmp2;
- if(!res){
- res = (char *)MALLOC(1);
- reslen = 1;
- }
- tmp2 = res;
- len2 = reslen;
- while(len){
- iconv(tr, (char **)&tmp, &len, &tmp2, &len2);
- #ifdef PACKAGE_DWLIB
- if(len > 1 && tmp[0] == 0xff && tmp[1] == 0xf9){
- len -=2;
- tmp +=2;
- #else
- if(0){
- #endif
- } else {
- if(E2BIG == errno){
- errno = 0;
- tmp = (unsigned char *)mes;
- len = strlen(mes)+1;
- FREE(res);
- reslen *= 2;
- res = (char *)MALLOC(reslen);
- tmp2 = res;
- len2 = reslen;
- continue;
- }
- tmp2[0] = 0;
- *outlen = reslen - len2;
- return res;
- }
- }
- *outlen = reslen - len2;
- return res;
- }
- #else
- char *translate(iconv_t tr, const char *mes, int inlen, int *outlen){
- *outlen = inlen;
- return (char *)mes;
- }
- #endif
- char *translate_easy(iconv_t tr, char *mes){
- int dummy;
- char *res = translate(tr, mes, strlen(mes)+1, &dummy);
- return res;
- }
- #ifdef F_SET_ENCODING
- void f_set_encoding(){
- if(current_object->interactive){
- struct translation *newt = get_translator((char *)sp->u.string);
- if(newt){
- current_object->interactive->trans = newt;
- return;
- }
- }
- pop_stack();
- push_number(0);
- }
- #endif
- #ifdef F_TO_UTF8
- void f_to_utf8(){
- struct translation *newt = get_translator((char *)sp->u.string);
- pop_stack();
- if(!newt)
- error("unknown encoding");
- char *text = (char *)sp->u.string;
- char *translated = translate_easy(newt->incoming, text);
- pop_stack();
- copy_and_push_string(translated);
- }
- #endif
- #ifdef F_UTF8_TO
- void f_utf8_to(){
- struct translation *newt = get_translator((char *)sp->u.string);
- pop_stack();
- if(!newt)
- error("unknown encoding");
- char *text = (char *)sp->u.string;
- char *translated = translate_easy(newt->outgoing, text);
- pop_stack();
- copy_and_push_string(translated);
- }
- #endif
- #ifdef F_STR_TO_ARR
- void f_str_to_arr(){
- static struct translation *newt = 0;
- if(!newt){
- newt = get_translator("UTF-32");
- translate_easy(newt->outgoing, " ");
- }
- int len;
- int *trans = (int *)translate(newt->outgoing, sp->u.string, SVALUE_STRLEN(sp)+1, &len);
- len/=4;
- array_t *arr = allocate_array(len);
- while(len--)
- arr->item[len].u.number = trans[len];
- free_svalue(sp, "str_to_arr");
- put_array(arr);
- }
- #endif
- #ifdef F_ARR_TO_STR
- void f_arr_to_str(){
- static struct translation *newt = 0;
- if(!newt){
- newt = get_translator("UTF-32");
- }
- int len = sp->u.arr->size;
- int *in = (int *)MALLOC(sizeof(int)*(len+1));
- char *trans;
- in[len] = 0;
- while(len--)
- in[len] = sp->u.arr->item[len].u.number;
- trans = translate(newt->incoming, (char *)in, (sp->u.arr->size+1)*4, &len);
- FREE(in);
- pop_stack();
- copy_and_push_string(trans);
- }
- #endif
- #ifdef F_STRWIDTH
- void f_strwidth(){
- int len = SVALUE_STRLEN(sp);
- int width = 0;
- int i;
- for(i=0; i<len; i++)
- width += !(((sp->u.string[i]) & 0xc0) == 0x80);
- pop_stack();
- push_number(width);
- }
- #endif