TIVI-153: Add as dependency for iputils
[profile/ivi/opensp.git] / lib / CharsetInfo.cxx
1 // Copyright (c) 1994, 1997 James Clark
2 // See the file COPYING for copying permission.
3
4 #ifdef __GNUG__
5 #pragma implementation
6 #endif
7 #include "splib.h"
8 #include "CharsetInfo.h"
9 #include "ISet.h"
10 #include "constant.h"
11
12 #ifdef SP_NAMESPACE
13 namespace SP_NAMESPACE {
14 #endif
15
16 CharsetInfo::CharsetInfo(const UnivCharsetDesc &desc)
17 : desc_(desc)
18 {
19   // FIXME remove mappings from desc for characters greater charMax
20   init();
21 }
22
23 CharsetInfo::CharsetInfo()
24 {
25   inverse_.setAll(unsigned(-1));
26 }
27
28 void CharsetInfo::set(const UnivCharsetDesc &desc)
29 {
30   desc_ = desc;
31   init();
32 }
33
34 void CharsetInfo::init()
35 {
36   inverse_.setAll(Unsigned32(-1));
37
38   UnivCharsetDescIter iter(desc_);
39   
40   WideChar descMin, descMax;
41   UnivChar univMin;
42   while (iter.next(descMin, descMax, univMin)) {
43     if (univMin <= charMax) {
44       Char univMax;
45       if (charMax - univMin < descMax - descMin)
46         univMax = charMax;
47       else
48         univMax = univMin + (descMax - descMin);
49       Unsigned32 diff
50         = ((descMin - univMin) & ((Unsigned32(1) << 31) - 1));
51       for (;;) {
52         Char max;
53         Unsigned32 n = inverse_.getRange(univMin, max);
54         if (max > univMax)
55           max = univMax;
56         if (n == Unsigned32(-1))
57           inverse_.setRange(univMin, max, diff);
58         else if (n != Unsigned32(-2))
59           inverse_.setRange(univMin, max, Unsigned32(-2));
60         if (max == univMax)
61           break;
62         univMin = max + 1;
63       }
64     }
65   }
66   // These are the characters that the ANSI C
67   // standard guarantees will be in the basic execution
68   // character set.
69   static char execChars[] =
70     "\t\n\r "
71     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
72     "abcdefghijklmnopqrstuvwxyz"
73     "0123456789"
74     "!\"#%&'()*+,-./:"
75     ";<=>?[\\]^_{|}~";
76   // These are the corresponding ISO 646 codes.
77   static char univCodes[] = {
78     9, 10, 13, 32,
79     65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
80     78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
81     97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
82     110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
83     48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
84     33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 58,
85     59, 60, 61, 62, 63, 91, 92, 93, 94, 95, 123, 124, 125, 126,
86   };
87   for (size_t i = 0; execChars[i] != '\0'; i++) {
88     WideChar c;
89     ISet<WideChar> set;
90     if (univToDesc(univCodes[i], c, set) > 0 && c <= charMax)
91       execToDesc_[(unsigned char)execChars[i]] = Char(c);
92   }
93 }
94
95 void CharsetInfo::getDescSet(ISet<Char> &set) const
96 {
97   UnivCharsetDescIter iter(desc_);
98   WideChar descMin, descMax;
99   UnivChar univMin;
100   while (iter.next(descMin, descMax, univMin)) {
101     if (descMin > charMax)
102       break;
103     if (descMax > charMax)
104       descMax = charMax;
105     set.addRange(Char(descMin), Char(descMax));
106   }
107 }
108
109 int CharsetInfo::digitWeight(Char c) const
110 {
111   for (int i = 0; i < 10; i++)
112     if (c == execToDesc('0' + i))
113       return i;
114   return -1;
115 }
116
117 int CharsetInfo::hexDigitWeight(Char c) const
118 {
119   for (int i = 0; i < 10; i++)
120     if (c == execToDesc('0' + i))
121       return i;
122   for (int i = 0; i < 6; i++)
123     if (c == execToDesc('a' + i) || c == execToDesc('A' + i))
124       return i + 10;
125   return -1;
126 }
127
128 StringC CharsetInfo::execToDesc(const char *s) const
129 {
130   StringC result;
131   while (*s != '\0')
132     result += execToDesc(*s++);
133   return result;
134 }
135
136 #ifdef SP_NAMESPACE
137 }
138 #endif