/rusxmms/librcc

To get this branch, use:
bzr branch http://suren.me/webbzr/rusxmms/librcc

« back to all changes in this revision

Viewing changes to src/recode.c

  • Committer: Suren A. Chilingaryan
  • Date: 2005-06-16 23:14:30 UTC
  • Revision ID: Arch-1:ds@dside.dyndns.org--darksoft-2004%librcc--main--0.1--base-0
Initial Import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
#include <locale.h>
 
5
 
 
6
#include <librcd.h>
 
7
#include "librcc.h"
 
8
 
 
9
#include "fs.h"
 
10
#include "config.h"
 
11
 
 
12
 
 
13
static void rccIConvCopySymbol(char **in_buf, int *in_left, char **out_buf, int *out_left) {
 
14
    if ((out_left>0)&&(in_left>0)) {
 
15
        (**out_buf)=(**in_buf);
 
16
        (*out_buf)++;
 
17
        (*in_buf)++;
 
18
        (*in_left)--;
 
19
        (*out_left)--;
 
20
    }
 
21
}
 
22
 
 
23
static int rccIConvUTFBytes(unsigned char c) {
 
24
    int j;
 
25
    if (c<128) return 1;
 
26
 
 
27
    for (j=6;j>=0;j--)
 
28
        if ((c&bit(j))==0) break;
 
29
            
 
30
    if ((j==0)||(j==6)) return 1;
 
31
    return 6-j;
 
32
}
 
33
 
 
34
static int rccIConv(rcc_context *ctx, iconv_t icnv, char *buf, int len) {
 
35
    char *in_buf, *out_buf, *res, err;
 
36
    int in_left, out_left, olen;
 
37
    int ub, utf_mode=0;
 
38
    int errors=0;
 
39
    
 
40
    if ((!buf)||(!ctx)||(icnv == (iconv_t)-1)) return -1;
 
41
    
 
42
    len = STRNLEN(buf,len);
 
43
    
 
44
    if (iconv(icnv, NULL, NULL, NULL, NULL) == -1) return -1;
 
45
    
 
46
loop_restart:
 
47
    errors = 0;
 
48
    in_buf = buf;
 
49
    in_left = len;
 
50
    out_buf = ctx->tmpbuffer;
 
51
    out_left = RCC_MAX_STRING_CHARS;
 
52
 
 
53
loop:
 
54
    err=iconv(icnv, &in_buf, &in_left, &out_buf, &out_left);
 
55
    if (err<0) {
 
56
        if (errno==E2BIG) {
 
57
            *(int*)(ctx->tmpbuffer+(CHARSET_MAX_STRING_SIZE-sizeof(int)))=0;
 
58
        } else if (errno==EILSEQ) {
 
59
            if (errors++<CHARSET_MAX_ERRORS) {
 
60
                for (ub=utf_mode?rccIConvUTFBytes(*in_buf):1;ub>0;ub--)
 
61
                    rccIConvCopySymbol(&in_buf, &in_left, &out_buf, &out_left);
 
62
                if (in_left>0) goto loop;
 
63
            } else if (!utf_mode) {
 
64
                utf_mode = 1;
 
65
                goto loop_restart;
 
66
            } else {
 
67
                return -1;
 
68
            }
 
69
        } else {
 
70
            return -1;
 
71
        }
 
72
    }
 
73
        
 
74
    return CHARSET_MAX_STRING_SIZE - out_left;
 
75
}
 
76
 
 
77
 
 
78
static charset_id rccIConvAuto(rcc_context *ctx, rcc_class_id class_id, char *buf, int len) {
 
79
    rcc_class_type class_type;
 
80
    
 
81
    if ((!ctx)||(!buf)) return -1;
 
82
 
 
83
    class_type = rccGetClassType(ctx, class_id);
 
84
    if ((class_type == RCC_CLASS_STANDARD)||((class_type == RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_AUTODETECT_FS_TITLES)))) {
 
85
        engine = rccGetCurrentEngine(ctx);
 
86
        if ((!engine)||(!engine->func)||(!stricmp(engine->title, "off"))||(!strcmp(engine->title, "dissable"))) return -1;
 
87
 
 
88
        return engine->func(buf, len);
 
89
    }
 
90
    
 
91
    return -1;
 
92
}
 
93
 
 
94
rcc_string rccFrom(rcc_context *ctx, rcc_class_id class_id, const char *buf, int len, int *rlen) {
 
95
    int err;
 
96
    rcc_language_id language_id;
 
97
    rcc_charset_id charset_id;
 
98
    iconv_t icnv = (iconv_t)-1;
 
99
    char *result;
 
100
 
 
101
    if ((!ctx)||(class_id<0)||(class_id>=ctx->n_classes)||(!buf)) return NULL;
 
102
    
 
103
    err = rccConfigure(ctx);
 
104
    if (err) return NULL;
 
105
 
 
106
 
 
107
    language_id = rccGetCurrentLanguage(ctx);
 
108
    // DS: Learning. check database (language_id)
 
109
 
 
110
    charset_id = rccIConvAuto(ctx, buf, len);
 
111
    if (charset_id > 0) icnv = ctx->iconv_auto[charset_id];
 
112
    if (icnv == (iconv_t)-1) {
 
113
        icnv = ctx->iconv_from[class_id];
 
114
        if (icnv == (iconv_t)-1) return NULL;
 
115
    }
 
116
    
 
117
    if (icnv == (iconv_t)-2) {
 
118
        result = rccCreateString(language_id, buf, len, rlen);
 
119
    } else { 
 
120
        err = rccIConv(ctx, icnv, buf, len);
 
121
        if (err<=0) return NULL;
 
122
        result = rccCreateString(language_id, ctx->tmpbuffer, err, rlen);
 
123
    }
 
124
    
 
125
    // DS: Learning. write database
 
126
    
 
127
    return result;
 
128
}
 
129
 
 
130
char *rccTo(rcc_context *ctx, rcc_class_id class_id, const rcc_string buf, int len, int *rlen) {
 
131
    int err;
 
132
    char *result;
 
133
    char *prefix, *name;
 
134
    rcc_language_id language_id;
 
135
    rcc_charset_id charset_id;
 
136
    iconv_t icnv;
 
137
    
 
138
    if ((!ctx)||(class_id<0)||(class_id>=ctx->n_classes)||(!buf)) return NULL;
 
139
 
 
140
    language_id = rccCheckString(ctx, buf);
 
141
    if (!language_id) return NULL;
 
142
 
 
143
    err = rccConfigure(ctx);
 
144
    if (err) return NULL;
 
145
 
 
146
    icnv =  ctx->iconv_to[class_id];
 
147
 
 
148
    if ((class_type == RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_AUTODETECT_FS_NAMES))) {
 
149
        // DS: file_names (autodetect fspath)
 
150
            prefix = NULL; name = buf + sizeof(rcc_string_header);
 
151
            err = rccFS0(NULL, buf, &prefix, &name);
 
152
            if (!err) {
 
153
                result = rccFS3(ctx, language_id, class_id, prefix, name, 0, rlen);
 
154
                return result;
 
155
            }
 
156
    }
 
157
    
 
158
    if (icnv == (iconv_t)-1) return NULL;
 
159
    if (icnv == (iconv_t)-2) {
 
160
        result = rccParseString(ctx, buf, len, rlen);
 
161
    } else {
 
162
        err = rccIConv(ctx, icnv, buf + sizeof(rcc_string_header), len?len-sizeof(rcc_string_header):0);
 
163
        if (err<=0) return NULL;
 
164
 
 
165
        result = rccCreateAnswer(ctx, err, rlen);
 
166
    }
 
167
    
 
168
    return result;
 
169
}
 
170
 
 
171
char *rccRecode(rcc_context *ctx, rcc_class_id from, rcc_class_id to, const char *buf, int len, int *rlen) {
 
172
    int nlen;
 
173
    rcc_string stmp;
 
174
    charset_id from_charset_id, to_charset_id;
 
175
 
 
176
    if ((!ctx)||(from<0)||(from>=ctx->n_classes)||(to<0)||(to>=ctx->n_classes)||(!buf)) return NULL;
 
177
 
 
178
    if ((class_type == RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_AUTODETECT_FS_NAMES))) goto recoding;
 
179
    
 
180
    from_charset_id = rccIConvAuto(ctx, buf, len);
 
181
    if (from_charset_id>0) {
 
182
        from_charset = rccGetAutoCharsetName(ctx, from_charset_id);
 
183
        to_charset = rccGetCurrentCharsetName(ctx, to);
 
184
        if ((from_charset)&&(to_charset)&&(!stricmp(from_charset, to_charset))) return NULL;
 
185
    } else {
 
186
        from_charset_id = rccGetCurrentCharset(ctx, from)
 
187
        to_charset_id = rccGetCurrentCharset(ctx, to);
 
188
        if (from_charset_id == to_charset_id) return NULL;
 
189
    }
 
190
 
 
191
recoding:    
 
192
    stmp = rccFrom(ctx, from, buf, len, &nlen);
 
193
    if (stmp) {
 
194
        buf = rccTo(ctx, to, stmp, nlen, rlen);
 
195
        free(stmp);
 
196
        return buf;
 
197
    } 
 
198
    
 
199
    return rccTo(ctx, to, buf, len, rlen);
 
200
}
 
201
 
 
202
char *rccFS(rcc_context *ctx, rcc_class_id from, rcc_class_id to, const char *fspath, const char *path, const char *filename) {
 
203
    int err;
 
204
    char *prefix = path, *name = filename;
 
205
    rcc_string string;
 
206
    
 
207
    char *stmp;
 
208
    char *result_fn = NULL;
 
209
    
 
210
    
 
211
    err = rccFS1(ctx, fspath, &prefix, &name);
 
212
    if (err) {
 
213
        if (err<0) return NULL;
 
214
        return name;
 
215
    }
 
216
 
 
217
    string = rccFrom(ctx, from, name, len, rlen);
 
218
    if (string) {
 
219
        language_id = rccGetCurrentLanguage(ctx);
 
220
        result = rccFS3(ctx, language_id, to, prefix, string + sizeof(rcc_string_header), 0, NULL);
 
221
        free(string);
 
222
    } else result = NULL;
 
223
    
 
224
    free(prefix);
 
225
    free(name);
 
226
 
 
227
    return result;
 
228
}