~ubuntu-branches/debian/wheezy/libnjb/wheezy

« back to all changes in this revision

Viewing changes to src/unicode.c

  • Committer: Bazaar Package Importer
  • Author(s): Shaun Jackman
  • Date: 2004-05-25 13:06:10 UTC
  • Revision ID: james.westby@ubuntu.com-20040525130610-vexcucw1qxq1g4dp
Tags: upstream-1.1
ImportĀ upstreamĀ versionĀ 1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "../config.h"
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
#include <errno.h>
 
5
#include "libnjb.h"
 
6
#include "njbusb.h"
 
7
#include "protocol.h"
 
8
#include "protocol3.h"
 
9
#include "unicode.h"
 
10
#include "njb_error.h"
 
11
#include "usb_io.h"
 
12
#include "ioutil.h"
 
13
#include "defs.h"
 
14
#include "base.h"
 
15
 
 
16
extern int __sub_depth;
 
17
int njb_unicode_flag = NJB_UC_8859;
 
18
#define MAX_STRING_LENGTH 512
 
19
 
 
20
/* This flag determines whether to use ISO 8859-1
 
21
 * or unicode UTF-8 for ALL strings */
 
22
void njb_set_unicode (int flag)
 
23
{
 
24
        njb_unicode_flag = flag;
 
25
}
 
26
 
 
27
/* Gets the length (in characters, not bytes) of a unicode 
 
28
 * UCS-2 string, eg a string which physically is 0x00 0x41 0x00 0x00
 
29
 * will return a value of 1. */
 
30
int ucs2strlen(const unsigned char *unicstr){
 
31
 
 
32
        __dsub= "ucs2strlen";
 
33
 
 
34
        int length=0;
 
35
        int i;
 
36
 
 
37
        __enter;
 
38
 
 
39
        /* Unicode strings are terminated with 2 * 0x00 */
 
40
        for(i=0; (unicstr[i] | unicstr[i+1])!='\0'; i+=2) {
 
41
                length++;
 
42
        }
 
43
 
 
44
        __leave;
 
45
        return length;
 
46
}
 
47
 
 
48
/* This routine returns the length in bytes that this
 
49
 * UCS-2 string would occupy if encoded as UTF-8 */
 
50
static int ucs2utf8len(const unsigned char *unicstr){
 
51
  int length=0;
 
52
  int i;
 
53
  for(i=0; (unicstr[i] | unicstr[i+1]) != '\0'; i+=2) {
 
54
    if (unicstr[i] == 0x00 && unicstr[i+1] < 0x80)
 
55
      length++;
 
56
    else if (unicstr[i] < 0x08)
 
57
      length+=2;
 
58
    else
 
59
      length+=3;
 
60
  }
 
61
  return length;
 
62
}
 
63
 
 
64
/* Create a new, allocated UCS-2 string that is a copy
 
65
 * of the parameter */
 
66
static unsigned char *ucs2strdup(const unsigned char *unicstr) {
 
67
  int length = ucs2strlen(unicstr);
 
68
  unsigned char *data;
 
69
  
 
70
  data= (char *) malloc(length*2+2);
 
71
  if ( data == NULL ) {
 
72
    return NULL;
 
73
  }
 
74
  memcpy(data, unicstr, length*2+2);
 
75
  return data;
 
76
}
 
77
 
 
78
/* This function converts an ordinary ISO 8859-1 string
 
79
 * to a unicode UTF-8 string */
 
80
char *strtoutf8(const unsigned char *str) {  
 
81
  unsigned char buffer[MAX_STRING_LENGTH];
 
82
  int l=0;
 
83
  int i;
 
84
 
 
85
  memset(buffer,0,MAX_STRING_LENGTH);
 
86
  
 
87
  for (i=0;i<strlen(str);i++) {
 
88
    if (str[i]<0x80) {
 
89
      buffer[l] = str[i];
 
90
      l++;
 
91
    } else {
 
92
      buffer[l] = 0xC0 | (str[i]>>6 & 0x03);
 
93
      buffer[l+1] = 0x80 | (str[i] & 0x3F);
 
94
      l+=2;
 
95
    }
 
96
    buffer[l] = 0x00;
 
97
  }
 
98
  /* The duplicate the string and return it */
 
99
  return strdup(buffer);
 
100
}
 
101
 
 
102
/* This function approximates an ISO 8859-1 string from
 
103
 * a UTF-8 string, leaving out untranslatable characters */
 
104
char *utf8tostr(const unsigned char *str) {
 
105
  unsigned char buffer[MAX_STRING_LENGTH];
 
106
  unsigned char *ucs2string;
 
107
  int i = 0;
 
108
  int l = 0;
 
109
 
 
110
  memset(buffer,0,MAX_STRING_LENGTH);
 
111
  
 
112
  ucs2string = strtoucs2(str);
 
113
  if (ucs2string == NULL)
 
114
    return NULL;
 
115
 
 
116
  for(i=0; (ucs2string[i] | ucs2string[i+1])!='\0'; i+=2) {
 
117
    if (ucs2string[i] == '\0') {
 
118
      buffer[l] = ucs2string[i+1];
 
119
      l++;
 
120
    }
 
121
  }
 
122
  buffer[l] = '\0';
 
123
 
 
124
  free(ucs2string);
 
125
 
 
126
  /* If there was nothing in this string, return NULL */
 
127
  if (l>0 || i == 0)
 
128
    return strdup(buffer);
 
129
  else
 
130
    return NULL;
 
131
}
 
132
 
 
133
/* Converts a unicode 2-byte string to a common string
 
134
 * quick and dirty (japanese unicodes etc, that use all 16 bits
 
135
 * will fail miserably) */
 
136
char *ucs2tostr(const unsigned char *unicstr){
 
137
 
 
138
        __dsub= "ucs2tostr";
 
139
 
 
140
        char *data = NULL;
 
141
        int i = 0;
 
142
        int l = 0;
 
143
 
 
144
        __enter;
 
145
 
 
146
 
 
147
        /* Real unicode support in UTF8 */
 
148
        if (njb_unicode_flag == NJB_UC_UTF8) {
 
149
          int length8 = ucs2utf8len(unicstr);
 
150
          data= (char *) malloc(length8+1);
 
151
          if ( data == NULL ) {
 
152
            NJB_ERROR(EO_NOMEM);
 
153
            __leave;
 
154
            return NULL;
 
155
          }
 
156
          for(l=0;(unicstr[l] | unicstr[l+1])!='\0'; l+=2) {
 
157
            if (unicstr[l] == 0x00 && unicstr[l+1] < 0x80) {
 
158
              data[i]=unicstr[l+1];
 
159
              i++;
 
160
            } else if (unicstr[l] < 0x08) {
 
161
              data[i] = 0xc0 | (unicstr[l]<<2 & 0x1C) | (unicstr[l+1]>>6  & 0x03);
 
162
              data[i+1] = 0x80 | (unicstr[l+1] & 0x3F);
 
163
              i+=2;
 
164
            } else {
 
165
              data[i] = 0xe0 | (unicstr[l]>>4 & 0x0F);
 
166
              data[i+1] = 0x80 | (unicstr[l]<<2 & 0x3C) | (unicstr[l+1]>>6 & 0x03);
 
167
              data[i+2] = 0x80 | (unicstr[l+1] & 0x3F);
 
168
              i+=3;
 
169
            }
 
170
          }
 
171
          /* Terminate string */
 
172
          data[i]=0x00;   
 
173
        } else {
 
174
          /* If we're running in ISO 8859-1 mode, approximate
 
175
           * and concatenate, loosing any chars above 0xff */
 
176
          int length=ucs2strlen(unicstr);
 
177
 
 
178
          data= (char *) malloc(length+1);
 
179
          if ( data == NULL ) {
 
180
            NJB_ERROR(EO_NOMEM);
 
181
            __leave;
 
182
            return NULL;
 
183
          }
 
184
 
 
185
          l = 0;
 
186
          for(i=0;l<length*2;){
 
187
            if (unicstr[l] == 0x00) {
 
188
              data[i]=unicstr[l+1];
 
189
              i++;
 
190
            }
 
191
            l+=2;
 
192
          }
 
193
          /* Terminate string */
 
194
          data[i]=0x00;
 
195
        }
 
196
 
 
197
 
 
198
        __leave;
 
199
        return data;
 
200
}
 
201
 
 
202
/* Convert a simple ISO 8859-1 or a Unicode
 
203
 * UTF8 string to a unicode UCS2 string */
 
204
unsigned char *strtoucs2(const unsigned char *str) {
 
205
 
 
206
        __dsub= "strtoucs2";
 
207
 
 
208
        unsigned char *data = NULL;
 
209
        int i=0;
 
210
        int l=0;
 
211
 
 
212
        __enter;
 
213
 
 
214
        /* Real unicode support in UTF8 */
 
215
        if (njb_unicode_flag == NJB_UC_UTF8) {
 
216
          unsigned char buffer[MAX_STRING_LENGTH*2];
 
217
 
 
218
          int length=0;
 
219
          int i;
 
220
 
 
221
          for(i=0; str[i] != '\0';) {
 
222
            if (str[i] < 0x80) {
 
223
              buffer[length] = 0x00;
 
224
              buffer[length+1] = str[i];
 
225
              length += 2;
 
226
              i++;
 
227
            } else {
 
228
              unsigned char numbytes = 0;
 
229
              unsigned char lenbyte = 0;
 
230
              
 
231
              /* Read the number of encoded bytes */
 
232
              lenbyte = str[i];
 
233
              while (lenbyte & 0x80) {
 
234
                numbytes++;
 
235
                lenbyte = lenbyte<<1;
 
236
              }
 
237
              /* UCS-2 can handle no more than 3 UTF-8 encoded bytes */
 
238
              if (numbytes <= 3) {
 
239
                if (numbytes == 2 && str[i+1] > 0x80) {
 
240
                  /* This character can always be handled correctly */
 
241
                  buffer[length] = (str[i]>>3 & 0x07);
 
242
                  buffer[length+1] = (str[i]<<6 & 0xC0) | (str[i+1] & 0x3F);
 
243
                  i += 2;
 
244
                  length += 2;
 
245
                } else if (numbytes == 3 && str[i+1] > 0x80 && str[i+2] > 0x80) {
 
246
                  buffer[length] = (str[i]<<4 & 0xF0) | (str[i+1]>>2 & 0x0F);
 
247
                  buffer[length+1]= (str[i+1]<<6 & 0xC0) | (str[i+2] & 0x3F);
 
248
                  i += 3;
 
249
                  length += 2;
 
250
                } else {
 
251
                  /* Abnormal string character, just skip */
 
252
                  i += numbytes;
 
253
                }
 
254
              } else {
 
255
                /* Just skip that character */
 
256
                i += numbytes;
 
257
              }
 
258
            }
 
259
          }
 
260
          /* Copy the buffer contents */
 
261
          buffer[length] = 0x00;
 
262
          buffer[length+1] = 0x00;
 
263
          data = ucs2strdup(buffer);
 
264
          if (data == NULL) {
 
265
            NJB_ERROR(EO_NOMEM);
 
266
            __leave;
 
267
            return NULL;
 
268
          }
 
269
        } else {
 
270
          /* If we're running in ISO 8859-1 mode, approximate
 
271
           * and concatenate, loosing any chars above 0xff */
 
272
          data= (unsigned char *) malloc(2*strlen(str)+2);
 
273
          if ( data == NULL ) {
 
274
            NJB_ERROR(EO_NOMEM);
 
275
            __leave;
 
276
            return NULL;
 
277
          }
 
278
        
 
279
          for(i=0;i<=strlen(str);i++){
 
280
            data[l]=0x00;
 
281
            data[l+1]=str[i];
 
282
            l+=2;
 
283
          }
 
284
        }
 
285
 
 
286
        __leave;
 
287
        return data;
 
288
}