source: trunk/src/symtab.c @ 169

Last change on this file since 169 was 169, checked in by lindanl, 11 years ago

UTF-16/32 validation.

File size: 11.5 KB
Line 
1#include "symtab.h"
2
3const int INIT_STRINGPOOL_SIZE = 4096;
4
5inline bool bit_test(unsigned char * bit_Map, int codepoint) {
6        return (bit_Map[codepoint/8] >> (7 - codepoint % 8)) & 1;
7}
8
9
10bool is_XML10_NameStrt_codepoint(int codepoint) {
11        switch (codepoint >> 12) {
12                case 0: return bit_test(NameStrt_XML10_0000_11FF, codepoint);
13                case 1: if (codepoint <= 0x11FF)
14                                return bit_test(NameStrt_XML10_0000_11FF, codepoint);
15                        else if (codepoint < 0x1E00) return false;
16                        else return bit_test(NameStrt_XML10_1E00_1FFF, codepoint & 0x1FF);
17                case 2: if (codepoint > 0x2182) return false;
18                        else return bit_test(NameStrt_XML10_2000_21FF, codepoint & 0x1FF);
19                case 3: if (codepoint > 0x312C) return false;
20                        else return bit_test(NameStrt_XML10_3000_31FF, codepoint & 0x1FF);
21                case 4: return codepoint >= 0x4E00;
22                case 5: case 6: case 7: case 8: return true;
23                case 9: return codepoint <= 0x9FA5;
24                case 0xA: return codepoint >= 0xAC00;
25                case 0xB: case 0xC: return true;
26                case 0xD: return codepoint <= 0xD7A3;
27                default: return false;
28        }
29}
30
31bool is_XML10_NameChar_codepoint(int codepoint) {
32        switch (codepoint >> 12) {
33                case 0: return bit_test(NameChar_XML10_0000_11FF, codepoint);
34                case 1: if (codepoint <= 0x11FF)
35                                return bit_test(NameChar_XML10_0000_11FF, codepoint);
36                        else if (codepoint < 0x1E00) return false;
37                        else return bit_test(NameStrt_XML10_1E00_1FFF, codepoint & 0x1FF);
38                case 2: if (codepoint > 0x2182) return false;
39                        else return bit_test(NameChar_XML10_2000_21FF, codepoint & 0x1FF);
40                case 3: if (codepoint > 0x312C) return false;
41                        else return bit_test(NameChar_XML10_3000_31FF, codepoint & 0x1FF);
42                case 4: return codepoint >= 0x4E00;
43                case 5: case 6: case 7: case 8: return true;
44                case 9: return codepoint <= 0x9FA5;
45                case 0xA:       return codepoint >= 0xAC00;
46                case 0xB: case 0xC: return true;
47                case 0xD: return codepoint <= 0xD7A3;
48                default: return false;
49        }
50}
51
52bool is_XML11_NameStrt_codepoint(int codepoint) {
53        if (likely(codepoint) <= 0x03FF) return bit_test(NameStrt_XML11_0000_03FF, codepoint);
54        else switch (codepoint >> 12) {
55                case 0: case 1: return true;
56                case 2: if (codepoint >= 0x2070) 
57                                if (codepoint <= 0x218F) return true;
58                                else return (codepoint >= 0x2C00) & (codepoint <= 0x2FEF);
59                        else return (codepoint >= 0x200C) & (codepoint <= 0x200D);
60                case 3: return codepoint >= 0x3001;
61                case 4: case 5: case 6: case 7: case 8: case 9: case 0xA: case 0xB: case 0xC: return true;
62                case 0xD: return codepoint <= 0xD7FF;
63                case 0xE: return false;
64                case 0xF: if (codepoint <= 0xFDCF) return codepoint >= 0xF900;
65                          else return (codepoint >= 0xFDF0) & (codepoint <= 0xFFFD);
66                default: return codepoint <= 0xEFFFF;
67        }
68}
69
70bool is_XML11_NameChar_codepoint(int codepoint) {
71        if (likely(codepoint) <= 0x03FF) return bit_test(NameChar_XML11_0000_03FF, codepoint);
72        else switch (codepoint >> 12) {
73                case 0: case 1: return true;
74                case 2: if (codepoint >= 0x2070) 
75                                if (codepoint <= 0x218F) return true;
76                                else return (codepoint >= 0x2C00) & (codepoint <= 0x2FEF);
77                        else if (codepoint <= 0x200D) return codepoint >= 0x200C;
78                        else return (codepoint == 0x203F) | (codepoint == 0x2040);
79                case 3: return codepoint >= 0x3001;
80                case 4: case 5: case 6: case 7: case 8: case 9: case 0xA: case 0xB: case 0xC: return true;
81                case 0xD: return codepoint <= 0xD7FF;
82                case 0xE: return false;
83                case 0xF: if (codepoint <= 0xFDCF) return codepoint >= 0xF900;
84                          else return (codepoint >= 0xFDF0) & (codepoint <= 0xFFFD);
85                default: return codepoint <= 0xEFFFF;
86        }
87}
88
89inline int XML_10_UTF8_NameStrt_bytes (unsigned char bytes[]) {
90        if (bytes[0] <= 0x7F) {
91                if (bit_test(NameStrt_XML10_0000_11FF, (int) bytes[0])) return 1;
92                else return 0;
93        }
94        else if (bytes[0] <= 0xDF) {
95                int codepoint = ((bytes[0] & 0x3F) << 6) | (bytes[1] & 0x3F);
96                if (bit_test(NameStrt_XML10_0000_11FF, codepoint)) return 2;
97                else return 0;
98        }
99        else if (bytes[0] <= 0xEF) {
100                int codepoint = ((bytes[0] & 0x0F) << 12)| ((bytes[1] & 0x3F) << 6) | (bytes[2] & 0x3F);
101                return is_XML10_NameStrt_codepoint(codepoint) ? 3 : 0;
102        }
103        else return 0;
104}
105
106inline int XML_10_UTF8_NameChar_bytes (unsigned char bytes[]) {
107        if (bytes[0] <= 0x7F) {
108                if (bit_test(NameChar_XML10_0000_11FF, (int) bytes[0])) return 1;
109                else return 0;
110        }
111        else if (bytes[0] <= 0xDF) {
112                int codepoint = ((bytes[0] & 0x3F) << 6) | (bytes[1] & 0x3F);
113                if (bit_test(NameChar_XML10_0000_11FF, codepoint)) return 2;
114                else return 0;
115        }
116        else if (bytes[0] <= 0xEF) {
117                int codepoint = ((bytes[0] & 0x0F) << 12)| ((bytes[1] & 0x3F) << 6) | (bytes[2] & 0x3F);
118                return is_XML10_NameChar_codepoint(codepoint) ? 3 : 0;
119        }
120        else return 0;
121}
122
123inline int XML_11_UTF8_NameStrt_bytes (unsigned char bytes[]) {
124        if (bytes[0] <= 0x7F) {
125                if (bit_test(NameStrt_XML11_0000_03FF, (int) bytes[0])) return 1;
126                else return 0;
127        }
128        else if (bytes[0] <= 0xDF) {
129                int codepoint = ((bytes[0] & 0x3F) << 6) | (bytes[1] & 0x3F);
130                return is_XML11_NameStrt_codepoint(codepoint) ? 2 : 0;
131        }
132        else if (bytes[0] <= 0xEF) {
133                int codepoint = ((bytes[0] & 0x0F) << 12)| ((bytes[1] & 0x3F) << 6) | (bytes[2] & 0x3F);
134                return is_XML11_NameStrt_codepoint(codepoint) ? 3 : 0;
135        }
136        else {
137                int codepoint = ((bytes[0] & 0x0F) << 18)| ((bytes[1] & 0x3F) << 12) | 
138                                ((bytes[2] & 0x3F) << 6) | (bytes[3] & 0x3F);
139                return is_XML11_NameStrt_codepoint(codepoint) ? 4 : 0;
140        }
141}
142
143inline int XML_11_UTF8_NameChar_bytes (unsigned char bytes[]) {
144        if (bytes[0] <= 0x7F) {
145                if (bit_test(NameChar_XML11_0000_03FF, (int) bytes[0])) return 1;
146                else return 0;
147        }
148        else if (bytes[0] <= 0xDF) {
149                int codepoint = ((bytes[0] & 0x3F) << 6) | (bytes[1] & 0x3F);
150                return is_XML11_NameChar_codepoint(codepoint) ? 2 : 0;
151        }
152        else if (bytes[0] <= 0xEF) {
153                int codepoint = ((bytes[0] & 0x0F) << 12)| ((bytes[1] & 0x3F) << 6) | (bytes[2] & 0x3F);
154                return is_XML11_NameChar_codepoint(codepoint) ? 3 : 0;
155        }
156        else {
157                int codepoint = ((bytes[0] & 0x0F) << 18)| ((bytes[1] & 0x3F) << 12) | 
158                                ((bytes[2] & 0x3F) << 6) | (bytes[3] & 0x3F);
159                return is_XML11_NameChar_codepoint(codepoint) ? 4 : 0;
160        }
161}
162
163bool is_XML10_UTF8_Name(char protoname[], int lgth) {
164        int valid_bytes = XML_10_UTF8_NameStrt_bytes((unsigned char *) protoname);
165        int pos = valid_bytes;
166        while ((valid_bytes > 0) & (pos < lgth)) {
167                valid_bytes = XML_10_UTF8_NameChar_bytes((unsigned char *) &protoname[pos]);
168                pos += valid_bytes;
169                 
170        }
171        /* Success requires that every byte sequence processed be valid
172           and that the total lgth processed be exactly that provided on
173           input. */
174         
175        return (valid_bytes > 0) & (pos == lgth);
176}
177
178bool is_XML11_UTF8_Name(char protoname[], int lgth) {
179        int valid_bytes = XML_11_UTF8_NameStrt_bytes((unsigned char *) protoname);
180        int pos = valid_bytes;
181        while ((valid_bytes > 0) & (pos < lgth)) {
182                valid_bytes = XML_11_UTF8_NameChar_bytes((unsigned char *) &protoname[pos]);
183                pos += valid_bytes;
184        }
185        /* Success requires that every byte sequence processed be valid
186           and that the total lgth processed be exactly that provided on
187           input. */
188        return (valid_bytes > 0) & (pos == lgth);
189}
190
191int Symbol_Table::Insert_Name(char * name, int lgth) {
192//      char * s = copy_name(name,lgth);
193        char * s = pool->Insert(name,lgth);
194        UTF8NameMap[s]=++(globalNameCount);
195        Name_Data name_data;
196        name_data.name_string = s;
197        name_data.lgth = lgth;
198        UTF8NameTable.push_back(name_data);
199        return globalNameCount;
200}
201
202
203inline bool Verify_ASCII(char * name_ptr, int name_lgth) {
204        /* To verify that a name is ASCII, ensure that the high bit
205           of each byte is 0.  A SIMD compare can verify this for
206           up to sizeof(BytePack) bytes.  For less than 16 bytes,
207           first shift out bytes beyond the name length.  For more
208           than 16 bytes, form the logical "or" of the successive byte
209           packs together so that a high 1 bit in any byte is preserved
210           for the final SIMD test. */
211        BytePack b = sisd_load_unaligned((BytePack *) name_ptr);
212        if (name_lgth <= sizeof(BytePack)) {
213                /* Clear bytes beyond the length of the name. */
214                b = sisd_sfl(b, sisd_from_int(8 * (sizeof(BytePack) - name_lgth)));
215        } 
216        else {
217                int offset = name_lgth % sizeof(BytePack);
218                for (int i = offset; i < name_lgth; i += sizeof(BytePack)) {
219                        b = simd_or(sisd_load_unaligned((BytePack *) &name_ptr[i]),b);
220                }
221        }
222        return !simd_any_sign_bit_8(b);
223}
224
225
226/* ASCII_LookupOrInsert determines the nameID for any ASCII name
227from the global name table, inserting the name and allocating
228a nameID if necessary.  If the name is non-ASCII, 0 is returned. */
229
230inline int Symbol_Table::ASCII_Lookup_or_Insert(char * name_ptr, int name_lgth) {
231
232        if (Verify_ASCII(name_ptr, name_lgth)) {
233                return UTF8_Lookup_or_Insert(name_ptr, name_lgth);
234        }
235        return 0;
236}
237
238
239
240int Symbol_Table::UTF8_Lookup_or_Insert(char * name, int lgth) {
241               
242        char delim = name[lgth];
243        name[lgth] = '\0';
244        int nameID = UTF8NameMap[name];
245        name[lgth] = delim;     
246       
247        if(nameID == 0){
248        #if (not defined(OMISSION)) or (OMISSION != NAME_VALIDATION)
249                if (!is_XML10_UTF8_Name(name,lgth))  {
250                        if (version == XML_1_1) {
251                                if (!is_XML11_UTF8_Name(name,lgth))  {
252                                        ShowSyntaxError(NT_Name);
253                                        exit(-1);
254                                }
255                        }
256                        else {
257                                ShowSyntaxError(NT_Name);
258                                exit(-1);
259                        }
260                }
261        #endif
262//              char * s = copy_name(name,lgth);
263                char * s = pool->Insert(name,lgth);
264                UTF8NameMap[s]=++(globalNameCount);
265                nameID = globalNameCount;
266                Name_Data name_data;
267                name_data.name_string = s;
268                name_data.lgth = lgth;
269                UTF8NameTable.push_back(name_data);
270//              UTF8NameTable.push_back(s);
271        }
272        return nameID;
273}
274
275//char * Symbol_Table::Get_UTF8_name(int nameID) {
276//      return  UTF8NameTable[nameID];
277//}
278
279char * Symbol_Table::Get_UTF8_name(int nameID) {
280        return  UTF8NameTable[nameID].name_string;
281}
282
283int Symbol_Table::Get_UTF8_lgth(int nameID) {
284        return  UTF8NameTable[nameID].lgth;
285}
286
287char * Symbol_Table::ReserveSymbolSpace(int u8_lgth) {
288        reserved = new char[u8_lgth+1];
289        reserved_lgth = u8_lgth;
290        return reserved;
291}
292
293int Symbol_Table::LookupOrInsertReserved(){             
294        int nameID = UTF8NameMap[reserved];
295        if(nameID == 0){
296        #if (not defined(OMISSION)) or (OMISSION != NAME_VALIDATION)
297                if (!is_XML10_UTF8_Name(reserved,reserved_lgth))  {
298                        ShowSyntaxError(NT_Name);
299                        exit(-1);
300                }
301        #endif
302                UTF8NameMap[reserved]=++(globalNameCount);
303                nameID = globalNameCount;
304                Name_Data name_data;
305                name_data.name_string = reserved;
306                name_data.lgth = reserved_lgth;
307                UTF8NameTable.push_back(name_data);
308//              UTF8NameTable.push_back(s);
309        }
310        else {
311                delete [] reserved;
312        }
313        return nameID;
314}
315
316Symbol_Table::Symbol_Table(){
317        globalNameCount = 0;
318        Name_Data name_data;
319        name_data.name_string = NULL;
320        name_data.lgth = 0;
321        UTF8NameTable.push_back(name_data);
322//      UTF8NameTable.push_back(NULL);
323        for (int i = 0; i < 5; i++) {
324                UTF8NameMap[predefined[i]] = ++(globalNameCount);
325                Name_Data name_data;
326                name_data.name_string = predefined[i];
327                name_data.lgth = strlen(predefined[i]);
328                UTF8NameTable.push_back(name_data);
329//              UTF8NameTable.push_back(predefined[i]);
330        }
331        pool = new StringPool;
332}
333
334
335StringPool::StringPool() {
336       buffer_capacity = INIT_STRINGPOOL_SIZE;
337       buffer_space_used = 0;
338       pool_buffers.push_back(new char [buffer_capacity]);
339}
340
341StringPool::~StringPool() {
342       vector<char * >::iterator i;
343       for (i = pool_buffers.begin(); i != pool_buffers.end(); i++) {
344               delete [] *i;
345       }
346}
347
348char * StringPool::Insert(char * s, int lgth) {
349       while (lgth + buffer_space_used >= buffer_capacity) {
350               buffer_capacity *= 2;
351               pool_buffers.push_back(new char [buffer_capacity]);
352               buffer_space_used = 0;
353       }
354       char * insertion_ptr = &pool_buffers.back()[buffer_space_used];
355       memcpy(insertion_ptr, s, lgth);
356       insertion_ptr[lgth] = '\0';
357       buffer_space_used += lgth + 1;
358       return insertion_ptr;
359}
360
361
362
Note: See TracBrowser for help on using the repository browser.