/rusxmms/librcd

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

« back to all changes in this revision

Viewing changes to src/librcd.c

  • Committer: Suren A. Chilingaryan
  • Date: 2005-06-16 23:19:27 UTC
  • Revision ID: Arch-1:ds@dside.dyndns.org--darksoft-2004%librcd--main--0.1--base-0
initial import

(automatically generated log message)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
 
 
3
#include "librcd.h"
 
4
 
 
5
#define NF_VALUE -2
 
6
#define max(a,b) ((a>b)?a:b)
 
7
#define min(a,b) ((a<b)?a:b)
 
8
#define bit(i) (1<<i)
 
9
#define STRNLEN(str,n) (n?strnlen(str,n):strlen(str))
 
10
 
 
11
 
 
12
typedef struct lng_stat2 {
 
13
  unsigned char a;
 
14
  unsigned char b;
 
15
  double rate;
 
16
  double srate;
 
17
  double erate;
 
18
} lng_stat2;
 
19
 
 
20
#include "russian_table.h"
 
21
 
 
22
 
 
23
static int end_symbol(char ch) {
 
24
    if (ch=='\r'||ch=='\n'||ch==0||ch==' '||ch=='\t'||ch==','||ch=='.'||ch=='!'||ch=='?'||ch==';'||ch=='-'||ch==':'||ch=='"'||ch=='\''||ch==')') return 1;
 
25
    return 0;
 
26
}
 
27
 
 
28
static int start_symbol(char ch) {
 
29
    if ((ch=='\t')||ch=='\r'||ch=='\n'||(ch==' ')||(ch=='(')||(ch=='"')||(ch=='\'')) return 1;
 
30
    return 0;
 
31
}    
 
32
 
 
33
typedef const struct lng_stat2 *lng_stat2_ptr;
 
34
 
 
35
static void bfind(const unsigned char *a, lng_stat2_ptr *w, lng_stat2_ptr *k, lng_stat2_ptr *al) {
 
36
  const struct lng_stat2 *winptr, *koiptr,*altptr;
 
37
  int ki,wi,ai,d,ws=0,ks=0,as=0;
 
38
    d=npow2>>1;
 
39
    wi=d;
 
40
    ki=d;
 
41
    ai=d;
 
42
    winptr=0;
 
43
    koiptr=0;
 
44
    altptr=0;
 
45
    do{
 
46
      d>>=1;
 
47
    
 
48
      if(!ws){
 
49
       if (wi>indexes2) wi-=d;
 
50
       else {
 
51
        winptr=enc_win+wi-1;
 
52
        if(a[0]==winptr->a){
 
53
          if(a[1]==winptr->b){
 
54
                ws=1;
 
55
          }else if(a[1]<winptr->b){
 
56
            wi-=d;
 
57
          }else{ //b>win[wi].b
 
58
            wi+=d;
 
59
          }
 
60
        }else if(a[0]<winptr->a){
 
61
          wi-=d;
 
62
        }else{ //a>win[wi].a
 
63
          wi+=d;
 
64
        }
 
65
       }
 
66
      }
 
67
      if(!ks){
 
68
       if (ki>indexes2) ki-=d;
 
69
       else {
 
70
        koiptr=enc_koi+ki-1;
 
71
        if(a[0]==koiptr->a){
 
72
          if(a[1]==koiptr->b){
 
73
                ks=1;
 
74
          }else if(a[1]<koiptr->b){
 
75
            ki-=d;
 
76
          }else{ //b>win[wi].b
 
77
            ki+=d;
 
78
          }
 
79
        }else if(a[0]<koiptr->a){
 
80
          ki-=d;
 
81
        }else{ //a>win[wi].a
 
82
          ki+=d;
 
83
        }
 
84
       }
 
85
      }
 
86
      if(!as){
 
87
       if (ai>indexes2) ai-=d;
 
88
       else {
 
89
        altptr=enc_alt+ai-1;
 
90
        if(a[0]==altptr->a){
 
91
          if(a[1]==altptr->b){
 
92
                as=1;
 
93
          }else if(a[1]<altptr->b){
 
94
            ai-=d;
 
95
          }else{ //b>win[wi].b
 
96
            ai+=d;
 
97
          }
 
98
        }else if(a[0]<altptr->a){
 
99
          ai-=d;
 
100
        }else{ //a>win[wi].a
 
101
          ai+=d;
 
102
        }
 
103
       }
 
104
      }
 
105
    }while(d);
 
106
    if (ws) *w=winptr;
 
107
    else *w=NULL;
 
108
    if (ks) *k=koiptr;
 
109
    else *k=NULL;
 
110
    if (as) *al=altptr;
 
111
    else *al=NULL;
 
112
}
 
113
 
 
114
static double calculate(double s, double m, double e) {
 
115
    return s+m+e;
 
116
}
 
117
 
 
118
static int is_win_charset2(const unsigned char *txt, int len){
 
119
  const struct lng_stat2 *winptr, *koiptr,*altptr;
 
120
  double winstep,koistep,altstep,winestep,koiestep,altestep,winsstep,koisstep,altsstep;
 
121
  double winstat=0,koistat=0,altstat=0,winestat=0,koiestat=0,altestat=0,winsstat=0,koisstat=0,altsstat=0;
 
122
  long j;
 
123
  
 
124
#ifdef _AUTO_DEBUG
 
125
  fprintf(stderr,"Word: %s\n",txt);
 
126
#endif
 
127
  for(j=0;j<len-1;j++){
 
128
    //skip bottom half of table
 
129
    if(txt[j]<128 || txt[j+1]<128) continue;
 
130
#ifdef _AUTO_DEBUG
 
131
    fprintf(stderr,"Pair: %c%c",txt[j],txt[j+1]);
 
132
#endif
 
133
    bfind(txt+j,&winptr,&koiptr,&altptr);
 
134
 
 
135
    if ((j==0)||(start_symbol(txt[j-1]))) {
 
136
        if (winptr) winsstep=winptr->srate;
 
137
        else winsstep=NF_VALUE;
 
138
        if (koiptr) koisstep=koiptr->srate;
 
139
        else koisstep=NF_VALUE;
 
140
        if (altptr) altsstep=altptr->srate;
 
141
        else altsstep=NF_VALUE;
 
142
        winestep=0;
 
143
        koiestep=0;
 
144
        altestep=0;
 
145
        winstep=0;
 
146
        koistep=0;
 
147
        altstep=0;
 
148
#ifdef _AUTO_DEBUG
 
149
        fprintf(stderr,", Win %lf, Koi %lf, Alt: %lf\n",winsstep,koisstep,altsstep);
 
150
#endif
 
151
    } else if ((j==len-2)||(end_symbol(txt[j+2]))) {
 
152
        if (winptr) winestep=winptr->erate;
 
153
        else winestep=NF_VALUE;
 
154
        if (koiptr) koiestep=koiptr->erate;
 
155
        else koiestep=NF_VALUE;
 
156
        if (altptr) altestep=altptr->erate;
 
157
        else altestep=NF_VALUE;
 
158
        winsstep=0;
 
159
        koisstep=0;
 
160
        altsstep=0;
 
161
        winstep=0;
 
162
        koistep=0;
 
163
        altstep=0;
 
164
#ifdef _AUTO_DEBUG
 
165
        fprintf(stderr,", Win %lf, Koi %lf, Alt %lf\n",winestep,koiestep,altestep);
 
166
#endif
 
167
    } else {
 
168
        if (winptr) winstep=winptr->rate;
 
169
        else winstep=NF_VALUE;
 
170
        if (koiptr) koistep=koiptr->rate;
 
171
        else koistep=NF_VALUE;
 
172
        if (altptr) altstep=altptr->rate;
 
173
        else altstep=NF_VALUE;
 
174
        winsstep=0;
 
175
        winestep=0;
 
176
        koisstep=0;
 
177
        koiestep=0;
 
178
        altsstep=0;
 
179
        altestep=0;
 
180
#ifdef _AUTO_DEBUG
 
181
        fprintf(stderr,", Win %lf, Koi %lf, Alt %lf\n",winstep,koistep,altstep);
 
182
#endif
 
183
    }
 
184
    
 
185
    winstat+=winstep;
 
186
    koistat+=koistep;
 
187
    altstat+=altstep;
 
188
    winsstat+=winsstep;
 
189
    koisstat+=koisstep;
 
190
    altsstat+=altsstep;
 
191
    winestat+=winestep;
 
192
    koiestat+=koiestep;
 
193
    altestat+=altestep;
 
194
  }
 
195
  
 
196
#ifdef _AUTO_DEBUG
 
197
  fprintf(stderr,"Start.  Win: %lf, Koi: %lf, Alt: %lf\n",winsstat,koisstat,altsstat);
 
198
  fprintf(stderr,"Middle. Win: %lf, Koi: %lf, Alt: %lf\n",winstat,koistat,altstat);
 
199
  fprintf(stderr,"End.    Win: %lf, Koi: %lf, Alt: %lf\n",winestat,koiestat,altestat);
 
200
  fprintf(stderr,"Final.  Win: %lf, Koi: %lf, Alt: %lf\n",calculate(winsstat,winstat,winestat),calculate(koisstat,koistat,koiestat),calculate(altsstat,altstat,altestat));
 
201
#endif
 
202
  if ((calculate(altsstat,altstat,altestat)>calculate(koisstat,koistat,koiestat))&&(calculate(altsstat,altstat,altestat)>calculate(winsstat,winstat,winestat))) return 3;
 
203
  if (calculate(koisstat,koistat,koiestat)>calculate(winsstat,winstat,winestat)) return 1;
 
204
  return 0;
 
205
}
 
206
 
 
207
 
 
208
static int check_utf8(const unsigned char *buf, int len) {
 
209
    long i,j;
 
210
    int bytes=0,rflag=0;
 
211
    unsigned char tmp;
 
212
    int res=0;
 
213
 
 
214
    for (i=0;i<len;i++) {
 
215
        if (buf[i]<128) continue;
 
216
        
 
217
        if (bytes>0) {
 
218
            if ((buf[i]&0xC0)==0x80) {
 
219
                if (rflag) {
 
220
                    tmp=buf[i]&0x3F;
 
221
                    // Russian is 0x410-0x44F
 
222
                    if ((rflag==1)&&(tmp>=0x10)) res++;
 
223
                    else if ((rflag==2)&&(tmp<=0x0F)) res++;
 
224
                }
 
225
                bytes--;
 
226
            } else {
 
227
                res--;
 
228
                bytes=1-bytes;
 
229
                rflag=0;
 
230
            }
 
231
        } else {
 
232
            for (j=6;j>=0;j--)
 
233
                if ((buf[i]&bit(j))==0) break;
 
234
            
 
235
            if ((j==0)||(j==6)) {
 
236
                if ((j==6)&&(bytes<0)) bytes++;
 
237
                else res--;
 
238
                continue;
 
239
            }
 
240
            bytes=6-j;
 
241
            if (bytes==1) {
 
242
                // Cyrrilic D0-D3, Russian - D0-D1
 
243
                if (buf[i]==0xD0) rflag=1;
 
244
                else if (buf[i]==0xD1) rflag=2;
 
245
            }
 
246
        }
 
247
            
 
248
        if ((buf[i]==0xD0)||(buf[i]==0xD1)) {
 
249
            if (i+1==len) break;
 
250
                    
 
251
        }
 
252
    }
 
253
    return res;
 
254
}
 
255
 
 
256
 
 
257
enum russian_charsets get_russian_charset(const char *buf,int len) {
 
258
    long l;
 
259
 
 
260
    l = STRNLEN(buf,len);
 
261
    if (check_utf8(buf,l)>1) return RUSSIAN_CHARSET_UTF8;
 
262
    return is_win_charset2(buf,l);
 
263
}