FreeBASIC  0.91.0
file_input_tok.c
Go to the documentation of this file.
1 /* input function core */
2 
3 #include "fb.h"
4 
5 static int hReadChar( FB_INPUTCTX *ctx )
6 {
7  /* device? */
8  if( FB_HANDLE_USED(ctx->handle) )
9  {
10  int res, c;
11  size_t len;
12  res = fb_FileGetDataEx( ctx->handle, 0, &c, 1, &len, FALSE, FALSE );
13  if( (res != FB_RTERROR_OK) || (len == 0) )
14  return EOF;
15 
16  return c & 0x000000FF;
17  }
18  /* console.. */
19  else
20  {
21  if( ctx->index >= FB_STRSIZE( &ctx->str ) )
22  return EOF;
23  else
24  return ctx->str.data[ctx->index++];
25  }
26 }
27 
28 static int hUnreadChar( FB_INPUTCTX *ctx, int c )
29 {
30  /* device? */
31  if( FB_HANDLE_USED(ctx->handle) )
32  {
33  return fb_FilePutBackEx( ctx->handle, &c, 1 );
34  }
35  /* console .. */
36  else
37  {
38  if( ctx->index <= 0 )
39  return FALSE;
40  else
41  {
42  --ctx->index;
43  return TRUE;
44  }
45  }
46 }
47 
49 {
50  int c;
51 
52  /* skip white space */
53  do
54  {
55  c = hReadChar( ctx );
56  if( c == EOF )
57  break;
58  } while( (c == ' ') || (c == '\t') );
59 
60  return c;
61 }
62 
63 static void hSkipDelimiter( FB_INPUTCTX *ctx, int c )
64 {
65  /* skip white space */
66  while( (c == ' ') || (c == '\t') )
67  c = hReadChar( ctx );
68 
69  switch( c )
70  {
71  case ',':
72  case EOF:
73  break;
74 
75  case '\n':
76  break;
77 
78  case '\r':
79  if( (c = hReadChar( ctx )) != '\n' )
80  hUnreadChar( ctx, c );
81  break;
82 
83  default:
84  hUnreadChar( ctx, c );
85  break;
86  }
87 }
88 
90  (
91  char *buffer,
92  ssize_t max_chars,
93  int is_string,
94  int *isfp
95  )
96 {
97  /* max_chars does not include the null terminator, the buffer is
98  assumed to be big enough to hold at least the null terminator */
99 
100  int c, isquote, hasamp, skipdelim;
101  ssize_t len;
102  FB_INPUTCTX *ctx = FB_TLSGETCTX( INPUT );
103 
104  *isfp = FALSE;
105 
106  /* */
107  skipdelim = TRUE;
108  isquote = FALSE;
109  hasamp = FALSE;
110  len = 0;
111 
112  c = hSkipWhiteSpc( ctx );
113 
114  while( (c != EOF) && (len < max_chars) )
115  {
116  switch( c )
117  {
118  case '\n':
119  skipdelim = FALSE;
120  goto exit;
121 
122  case '\r':
123  if( (c = hReadChar( ctx )) != '\n' )
124  hUnreadChar( ctx, c );
125 
126  skipdelim = FALSE;
127  goto exit;
128 
129  case '"':
130  if( !isquote )
131  {
132  if( len == 0 )
133  isquote = TRUE;
134  else
135  goto savechar;
136  }
137  else
138  {
139  isquote = FALSE;
140  if( is_string )
141  {
142  c = hReadChar( ctx );
143  goto exit;
144  }
145  }
146 
147  break;
148 
149  case ',':
150  if( !isquote )
151  {
152  skipdelim = FALSE;
153  goto exit;
154  }
155 
156  goto savechar;
157 
158  case '&':
159  hasamp = TRUE;
160  goto savechar;
161 
162  case 'd':
163  case 'D':
164  /* NOTE: if exponent letter is d|D, and
165  * is_string == FALSE, then convert the d|D
166  * to an e|E. strtod() which
167  * will later be used to convert the string
168  * to float won't accept d|D anywhere but
169  * on windows. (jeffm)
170  */
171  if( !hasamp && !is_string )
172  {
173  ++c;
174  }
175  /* fall through */
176 
177  case 'e':
178  case 'E':
179  case '.':
180  if( !hasamp )
181  {
182  *isfp = TRUE;
183  }
184  goto savechar;
185 
186  case '\t':
187  case ' ':
188  if( !isquote )
189  {
190  if( !is_string )
191  {
192  goto exit;
193  }
194  }
195 
196  default:
197 savechar:
198  *buffer++ = c;
199  ++len;
200  break;
201  }
202 
203  c = hReadChar( ctx );
204  }
205 
206 exit:
207  /* add the null-term */
208  *buffer = '\0';
209 
210  /* skip comma or newline */
211  if( skipdelim )
212  hSkipDelimiter( ctx, c );
213 
214  return len;
215 }