Include <ctype.h>.
[chise/concord.git] / read.c
1 /* Copyright (C) 2013 MORIOKA Tomohiko
2    This file is part of the CONCORD Library.
3
4    The CONCORD Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The CONCORD Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the CONCORD Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <stdlib.h>
20 #include <ctype.h>
21 #include "cos-read.h"
22
23 COS_object
24 cos_read_int (unsigned char *str, size_t len, size_t start, size_t* endp)
25 {
26   size_t i = start;
27   int c;
28   int negative_flag;
29   int dest;
30
31   if ( i < len )
32     {
33       switch ( str[i] )
34         {
35         case '+':
36           negative_flag = 0;
37           i++;
38           break;
39         case '-':
40           negative_flag = 1;
41           i++;
42           break;
43         default:
44           negative_flag = 0;
45         }
46
47       if ( (i < len) && (c = str[i++])
48            && ('0' <= c) && (c <= '9') )
49         {
50           dest = c - '0';
51
52           while ( i < len )
53             {
54               c = str[i];
55               if ( ('0' <= c) && (c <= '9') )
56                 {
57                   dest = dest * 10 + c - '0';
58                   i++;
59                 }
60               else if ( isspace (c) )
61                 {
62                   *endp = i;
63                   return cos_make_int ( negative_flag ? - dest : dest );
64                 }
65               else
66                 return NULL;
67             }
68           *endp = i;
69           return cos_make_int ( negative_flag ? - dest : dest );
70         }
71     }
72   return NULL;
73 }
74
75
76 int
77 cos_read_utf8 (unsigned char *str, size_t len, size_t start, size_t* endp)
78 {
79   size_t i = start;
80
81   if ( len >= i + 1 )
82     {
83       unsigned char c = str[i++];
84       int counter;
85       int cid;
86
87       if ( c < 0xC0 )
88         {
89           cid = c;
90           counter = 0;
91         }
92       else if ( c < 0xE0 )
93         {
94           cid = c & 0x1f;
95           counter = 1;
96         }
97       else if ( c < 0xF0 )
98         {
99           cid = c & 0x0f;
100           counter = 2;
101         }
102       else if ( c < 0xF8 )
103         {
104           cid = c & 0x07;
105           counter = 3;
106         }
107       else if ( c < 0xFC )
108         {
109           cid = c & 0x03;
110           counter = 4;
111         }
112       else
113         {
114           cid = c & 0x01;
115           counter = 5;
116         }
117
118       if (counter + i <= len)
119         {
120           int j;
121
122           for (j = 0; j < counter; j++)
123             cid = (cid << 6) | (str[i++] & 0x3F);
124           *endp = i;
125           return cid;
126         }
127     }
128   return -1;
129 }
130
131 int
132 cos_read_char (unsigned char *str, size_t len, size_t start, size_t* endp)
133 {
134   size_t i = start;
135
136   if ( (len >= start + 2) && (str[i++] == '?') )
137     {
138       if ( (len >= start + 3) && (str[i] == '\\') )
139         {
140           i++;
141           return cos_read_utf8 (str, len, i, endp);
142         }
143       else
144         return cos_read_utf8 (str, len, i, endp);
145     }
146
147   return -1;
148 }
149
150
151 COS_String
152 cos_read_string (unsigned char *str, size_t len, size_t start, size_t* endp)
153 {
154   size_t i = start;
155   int c;
156
157   if ( (len >= start + 2) && (str[i++] == '"') )
158     {
159       while ( ( i < len )
160               && ( (c = cos_read_utf8 (str, len, i, &i)) >= 0 )
161               )
162         {
163           if ( c == '"' )
164             {
165               return cos_make_string ((char*)&str[1], i - 2);
166             }
167           else if ( c == '\\' )
168             {
169               i++;
170               if ( cos_read_utf8 (str, len, i, &i) < 0 )
171                 return NULL;
172             }
173         }
174     }
175   return NULL;
176 }