~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/Data/String/analyze.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : analyze.cpp
 
4
* DESCRIPTION: Properties of characters and strings
 
5
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
 
6
*******************************************************************************
 
7
* This software falls under the GNU general public license and comes WITHOUT
 
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
 
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
 
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
11
******************************************************************************/
 
12
 
 
13
#include "string.hpp"
 
14
 
 
15
/******************************************************************************
 
16
* Tests for caracters
 
17
******************************************************************************/
 
18
 
 
19
bool
 
20
is_alpha (register char c) {
 
21
  return ((c>='a') && (c<='z')) || ((c>='A') && (c<='Z'));
 
22
}
 
23
 
 
24
bool
 
25
is_iso_alpha (register char c) {
 
26
  int i= ((int) ((unsigned char) c));
 
27
  return
 
28
    ((c>='a') && (c<='z')) ||
 
29
    ((c>='A') && (c<='Z')) ||
 
30
    ((i >= 128) && (i != 159) && (i != 189) && (i != 190) && (i != 191));
 
31
}
 
32
 
 
33
bool
 
34
is_locase (register char c) {
 
35
  int code= (int) ((unsigned char) c);
 
36
  return
 
37
    ((c>='a') && (c<='z')) ||
 
38
    ((code >= 160) && (code < 189)) ||
 
39
    (code >= 224);
 
40
}
 
41
 
 
42
bool
 
43
is_upcase (register char c) {
 
44
  int code= (int) ((unsigned char) c);
 
45
  return
 
46
    ((c>='A') && (c<='Z')) ||
 
47
    ((code >= 128) && (code < 159)) ||
 
48
    ((code >= 192) && (code < 224));
 
49
}
 
50
 
 
51
bool
 
52
is_digit (register char c) {
 
53
  return (c>='0') && (c<='9');
 
54
}
 
55
 
 
56
bool
 
57
is_numeric (register char c) {
 
58
  return ((c>='0') && (c<='9')) || (c=='.');
 
59
}
 
60
 
 
61
bool
 
62
is_ponctuation (register char c) {
 
63
  return
 
64
    (c=='.') || (c==',') || (c==':') || (c=='\'') || (c=='`') ||
 
65
    (c==';') || (c=='!') || (c=='?');
 
66
}
 
67
 
 
68
bool
 
69
is_space (register char c) {
 
70
  return (c == ' ') || (c == '\11') || (c == '\12') || (c == '\15');\
 
71
}
 
72
 
 
73
/******************************************************************************
 
74
* Tests for strings
 
75
******************************************************************************/
 
76
 
 
77
bool
 
78
is_alpha (string s) {
 
79
  int i;
 
80
  if (N(s)==0) return false;
 
81
  for (i=0; i<N(s); i++)
 
82
    if (!is_alpha (s[i])) return false;
 
83
  return true;
 
84
}
 
85
 
 
86
bool
 
87
is_iso_alpha (string s) {
 
88
  int i;
 
89
  if (N(s)==0) return false;
 
90
  for (i=0; i<N(s); i++)
 
91
    if (!is_iso_alpha (s[i])) return false;
 
92
  return true;
 
93
}
 
94
 
 
95
bool
 
96
is_numeric (string s) {
 
97
  int i;
 
98
  if (N(s)==0) return false;
 
99
  for (i=0; i<N(s); i++)
 
100
    if (!is_numeric (s[i])) return false;
 
101
  return true;
 
102
}
 
103
 
 
104
/******************************************************************************
 
105
* Changing cases
 
106
******************************************************************************/
 
107
 
 
108
string
 
109
upcase_first (string s) {
 
110
  if ((N(s)==0) || (!is_locase (s[0]))) return s;
 
111
  return string ((char) (((int) ((unsigned char) s[0]))-32)) * s (1, N(s));
 
112
}
 
113
 
 
114
string
 
115
locase_first (string s) {
 
116
  if ((N(s)==0) || (!is_upcase (s[0]))) return s;
 
117
  return string ((char) (((int) ((unsigned char) s[0]))+32)) * s (1, N(s));
 
118
}
 
119
 
 
120
string
 
121
upcase_all (string s) {
 
122
  int i;
 
123
  string r (N(s));
 
124
  for (i=0; i<N(s); i++)
 
125
    if (!is_locase (s[i])) r[i]= s[i];
 
126
    else r[i]= (char) (((int) ((unsigned char) s[i]))-32);
 
127
  return r;
 
128
}
 
129
 
 
130
string
 
131
locase_all (string s) {
 
132
  int i;
 
133
  string r (N(s));
 
134
  for (i=0; i<N(s); i++)
 
135
    if (!is_upcase (s[i])) r[i]= s[i];
 
136
    else r[i]= (char) (((int) ((unsigned char) s[i]))+32);
 
137
  return r;
 
138
}
 
139
 
 
140
/******************************************************************************
 
141
* Spanish in relation with ispell
 
142
******************************************************************************/
 
143
 
 
144
string
 
145
ispanish_to_spanish (string s) {
 
146
  int i, n= N(s);
 
147
  string r;
 
148
  for (i=0; i<n; i++)
 
149
    if ((s[i] == '\'') && ((i+1)<n)) {
 
150
      switch (s[i+1]) {
 
151
      case 'A': r << 'ļæ½'; break;
 
152
      case 'E': r << 'ļæ½'; break;
 
153
      case 'I': r << 'ļæ½'; break;
 
154
      case 'N': r << 'ļæ½'; break;
 
155
      case 'O': r << 'ļæ½'; break;
 
156
      case 'U': r << 'ļæ½'; break;
 
157
      case 'Y': r << 'ļæ½'; break;
 
158
      case 'a': r << 'ļæ½'; break;
 
159
      case 'e': r << 'ļæ½'; break;
 
160
      case 'i': r << 'ļæ½'; break;
 
161
      case 'n': r << 'ļæ½'; break;
 
162
      case 'o': r << 'ļæ½'; break;
 
163
      case 'u': r << 'ļæ½'; break;
 
164
      case 'y': r << 'ļæ½'; break;
 
165
      default : r << '\'' << s[i+1];
 
166
      }
 
167
      i++;
 
168
    }
 
169
    else r << s[i];
 
170
  return r;
 
171
}
 
172
 
 
173
string
 
174
spanish_to_ispanish (string s) {
 
175
  int i, n= N(s);
 
176
  string r;
 
177
  for (i=0; i<n; i++)
 
178
    switch (s[i]) {
 
179
    case 'ļæ½': r << "'A"; break;
 
180
    case 'ļæ½': r << "'E"; break;
 
181
    case 'ļæ½': r << "'I"; break;
 
182
    case 'ļæ½': r << "'N"; break;
 
183
    case 'ļæ½': r << "'O"; break;
 
184
    case 'ļæ½': r << "'U"; break;
 
185
    case 'ļæ½': r << "'Y"; break;
 
186
    case 'ļæ½': r << "'a"; break;
 
187
    case 'ļæ½': r << "'e"; break;
 
188
    case 'ļæ½': r << "'i"; break;
 
189
    case 'ļæ½': r << "'n"; break;
 
190
    case 'ļæ½': r << "'o"; break;
 
191
    case 'ļæ½': r << "'u"; break;
 
192
    case 'ļæ½': r << "'y"; break;
 
193
    default : r << s[i];
 
194
    }
 
195
  return r;
 
196
}
 
197
 
 
198
string
 
199
igerman_to_german (string s) {
 
200
  int i, n= N(s);
 
201
  string r;
 
202
  for (i=0; i<n; i++)
 
203
    if (s[i] == 'ļæ½') r << 'ļæ½';
 
204
    else r << s[i];
 
205
  return r;
 
206
}
 
207
 
 
208
string
 
209
german_to_igerman (string s) {
 
210
  int i, n= N(s);
 
211
  string r;
 
212
  for (i=0; i<n; i++)
 
213
    if (s[i] == 'ļæ½') r << 'ļæ½';
 
214
    else r << s[i];
 
215
  return r;
 
216
}
 
217
 
 
218
/******************************************************************************
 
219
* Iso latin 2 encoding for polish and czech
 
220
******************************************************************************/
 
221
 
 
222
static string il2_to_cork_string=
 
223
  "ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ ļæ½ļæ½ ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ ļæ½ ļæ½ļæ½ļæ½ ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½Ā€Äˆļæ½ĒƒÉ†Ė…ļæ½Ī„Š‹ļæ½ļæ½ŌŽļæ½.ļæ½ļæ½Ś–ļæ½Ż•ļæ½ļæ½ļæ½ļæ½äØ¢ļæ½ļæ½ļæ½ļæ½ī¤žļæ½ļæ½ļæ½ļæ½ļæ½ļæ½/ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ ";
 
224
static string cork_to_il2_string=
 
225
  "Ć”ļæ½ļæ½ļæ½ļæ½ļæ½GÅ„ļæ½ļæ½ļæ½ ļæ½ļæ½Ų¦ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½Yļæ½ļæ½ļæ½IIļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½gåµ³ļæ½ļæ½ ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½yļæ½ļæ½ļæ½i!?LAļæ½ļæ½Aļæ½AAļæ½Eļæ½Eļæ½Iļæ½ļæ½Iļæ½NOļæ½ļæ½Oļæ½OOUļæ½Uļæ½ļæ½ Saļæ½ļæ½aļæ½aaļæ½eļæ½eļæ½iļæ½ļæ½iļæ½noļæ½ļæ½oļæ½oouļæ½uļæ½ļæ½ ļæ½";
 
226
 
 
227
static char
 
228
il2_to_cork (char c) {
 
229
  int i= (int) ((unsigned char) c);
 
230
  if (i<128) return c;
 
231
  return il2_to_cork_string [i-128];
 
232
}
 
233
 
 
234
static char
 
235
cork_to_il2 (char c) {
 
236
  int i= (int) ((unsigned char) c);
 
237
  if (i<128) return c;
 
238
  return cork_to_il2_string [i-128];
 
239
}
 
240
 
 
241
string
 
242
il2_to_cork (string s) {
 
243
  int i, n= N(s);
 
244
  string r (n);
 
245
  for (i=0; i<n; i++)
 
246
    r[i]= il2_to_cork (s[i]);
 
247
  return r;
 
248
}
 
249
 
 
250
string
 
251
cork_to_il2 (string s) {
 
252
  int i, n= N(s);
 
253
  string r (n);
 
254
  for (i=0; i<n; i++)
 
255
    r[i]= cork_to_il2 (s[i]);
 
256
  return r;
 
257
}
 
258
 
 
259
/******************************************************************************
 
260
* Koi8 encoding for russian
 
261
******************************************************************************/
 
262
 
 
263
static string koi8_to_iso_string=
 
264
  "ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½";
 
265
static string iso_to_koi8_string=
 
266
  "ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½";
 
267
 
 
268
static char
 
269
koi8_to_iso (char c, bool ukrainian) {
 
270
  int i= (int) ((unsigned char) c);
 
271
  if (i==156) return 'ļæ½';
 
272
  if (i==188) return 'ļæ½';
 
273
  if (ukrainian)
 
274
  {
 
275
     switch(c)
 
276
     {
 
277
         case 'I':return 'ļæ½';
 
278
         case 'ļæ½':return 'ļæ½';
 
279
         case 'ļæ½':return 'ļæ½';
 
280
         case 'ļæ½':return 'ļæ½';
 
281
         case 'i':return 'ļæ½';
 
282
         case 'ļæ½':return 'ļæ½';
 
283
         case 'ļæ½':return 'ļæ½';
 
284
         case 'ļæ½':return 'ļæ½';
 
285
     }
 
286
  }
 
287
  if (i<192) return c;
 
288
  return koi8_to_iso_string [i-192];
 
289
}
 
290
 
 
291
static char
 
292
iso_to_koi8 (char c, bool ukrainian) {
 
293
  int i= (int) ((unsigned char) c);
 
294
  if (c=='ļæ½') return (char) 156;
 
295
  if (c=='ļæ½') return (char) 188;
 
296
  if (ukrainian)
 
297
  {
 
298
     switch(c)
 
299
     {
 
300
         case 'ļæ½':return 'I';
 
301
         case 'ļæ½':return 'ļæ½';
 
302
         case 'ļæ½':return 'ļæ½';
 
303
         case 'ļæ½':return 'ļæ½';
 
304
         case 'ļæ½':return 'i';
 
305
         case 'ļæ½':return 'ļæ½';
 
306
         case 'ļæ½':return 'ļæ½';
 
307
         case 'ļæ½':return 'ļæ½';
 
308
     }
 
309
  }
 
310
  if (i<192) return c;
 
311
  return iso_to_koi8_string [i-192];
 
312
}
 
313
 
 
314
string
 
315
koi8_to_iso (string s) {
 
316
  int i, n= N(s);
 
317
  string r (n);
 
318
  for (i=0; i<n; i++)
 
319
    r[i]= koi8_to_iso (s[i], false);
 
320
  return r;
 
321
}
 
322
 
 
323
string
 
324
iso_to_koi8 (string s) {
 
325
  int i, n= N(s);
 
326
  string r (n);
 
327
  for (i=0; i<n; i++)
 
328
    r[i]= iso_to_koi8 (s[i], false);
 
329
  return r;
 
330
}
 
331
 
 
332
string
 
333
koi8uk_to_iso (string s) {
 
334
  int i, n= N(s);
 
335
  string r (n);
 
336
  for (i=0; i<n; i++)
 
337
    r[i]= koi8_to_iso (s[i], true);
 
338
  return r;
 
339
}
 
340
 
 
341
string
 
342
iso_to_koi8uk (string s) {
 
343
  int i, n= N(s);
 
344
  string r (n);
 
345
  for (i=0; i<n; i++)
 
346
    r[i]= iso_to_koi8 (s[i], true);
 
347
  return r;
 
348
}
 
349
 
 
350
/******************************************************************************
 
351
* Convert between TeXmacs and XML strings
 
352
******************************************************************************/
 
353
 
 
354
static bool
 
355
is_xml_name (char c) {
 
356
  return
 
357
    is_alpha (c) || is_numeric (c) ||
 
358
    (c == '.') || (c == '-') || (c == ':');
 
359
}
 
360
 
 
361
string
 
362
tm_to_xml_name (string s) {
 
363
  string r;
 
364
  int i, n= N(s);
 
365
  for (i=0; i<n; i++)
 
366
    if (is_xml_name (s[i])) r << s[i];
 
367
    else r << "_" << as_string ((int) ((unsigned char) s[i])) << "_";
 
368
  return r;
 
369
}
 
370
 
 
371
string
 
372
xml_name_to_tm (string s) {
 
373
  string r;
 
374
  int i, n= N(s);
 
375
  for (i=0; i<n; i++)
 
376
    if (s[i] != '_') r << s[i];
 
377
    else {
 
378
      int start= ++i;
 
379
      while ((i<n) && (s[i]!='_')) i++;
 
380
      r << (char) ((unsigned char) as_int (s (start, i)));
 
381
    }
 
382
  return r;
 
383
}
 
384
 
 
385
string
 
386
tm_to_xml_cdata (string s) {
 
387
  string r;
 
388
  int i, n= N(s);
 
389
  for (i=0; i<n; i++)
 
390
    if (s[i] == '&') r << "&amp;";
 
391
    else if (s[i] == '>') r << "&gt;";
 
392
    else if (s[i] != '<') r << s[i];
 
393
    else {
 
394
      int start= ++i;
 
395
      while ((i<n) && (s[i]!='>')) i++;
 
396
      r << "&" << tm_to_xml_name (s (start, i)) << ";";
 
397
    }
 
398
  return r;
 
399
}
 
400
 
 
401
string
 
402
xml_cdata_to_tm (string s) {
 
403
  string r;
 
404
  int i, n= N(s);
 
405
  for (i=0; i<n; i++)
 
406
    if (s[i] == '<') r << "<less>";
 
407
    else if (s[i] == '>') r << "<gtr>";
 
408
    else if (s[i] != '&') r << s[i];
 
409
    else {
 
410
      int start= ++i;
 
411
      while ((i<n) && (s[i]!=';')) i++;
 
412
      string x= "<" * xml_name_to_tm (s (start, i)) * ">";
 
413
      if (x == "<amp>") r << "&";
 
414
      else r << x;
 
415
    }
 
416
  return r;
 
417
}
 
418
 
 
419
string
 
420
xml_unspace (string s, bool first, bool last) {
 
421
  string r;
 
422
  int i= 0, n= N(s);
 
423
  if (first) while ((i<n) && is_space (s[i])) i++;
 
424
  while (i<n)
 
425
    if (!is_space (s[i])) r << s[i++];
 
426
    else {
 
427
      while ((i<n) && is_space (s[i])) i++;
 
428
      if ((i<n) || (!last)) r << ' ';
 
429
    }
 
430
  return r;
 
431
}
 
432
 
 
433
/******************************************************************************
 
434
* Roman and alpha numbers
 
435
******************************************************************************/
 
436
 
 
437
static string ones[10]= {
 
438
  "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" };
 
439
static string tens[10]= {
 
440
  "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" };
 
441
static string hundreds[10]= {
 
442
  "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" };
 
443
 
 
444
string
 
445
roman_nr (int nr) {
 
446
  if (nr<0) return "-" * roman_nr (nr);
 
447
  if (nr==0) return "o";
 
448
  if (nr>1000) return "m" * roman_nr (nr-1000);
 
449
  if (nr==1000) return "m";
 
450
  if (nr==999) return "im";
 
451
  if (nr==499) return "id";
 
452
  if ((nr%100)==99) return hundreds[nr/100] * "ic";
 
453
  if ((nr%100)==49) return hundreds[nr/100] * "il";
 
454
  return hundreds[nr/100] * tens[(nr%100)/10] * ones[nr%10];
 
455
}
 
456
 
 
457
string
 
458
Roman_nr (int nr) {
 
459
  return upcase_all (roman_nr (nr));
 
460
}
 
461
 
 
462
string
 
463
alpha_nr (int nr) {
 
464
  if (nr<0) return "-" * alpha_nr (nr);
 
465
  if (nr==0) return "0";
 
466
  if (nr<=26) return string ((char) (((int) 'a')+ nr-1));
 
467
  return alpha_nr ((nr-1)/26) * alpha_nr (((nr-1)%26)+1);
 
468
}
 
469
 
 
470
string
 
471
Alpha_nr (int nr) {
 
472
  return upcase_all (alpha_nr (nr));
 
473
}
 
474
 
 
475
/******************************************************************************
 
476
* Conversions to and from hexadecimal
 
477
******************************************************************************/
 
478
 
 
479
static char* hex_string= "0123456789ABCDEF";
 
480
 
 
481
string
 
482
as_hexadecimal (int i) {
 
483
  if (i<0) return "-" * as_hexadecimal (-i);
 
484
  if (i<16) return hex_string [i & 15];
 
485
  return as_hexadecimal (i >> 4) * hex_string [i & 15];
 
486
}
 
487
 
 
488
string
 
489
as_hexadecimal (int i, int len) {
 
490
  if (len==1) return hex_string [i & 15];
 
491
  else return as_hexadecimal (i >> 4, len-1) * hex_string [i & 15];
 
492
}
 
493
 
 
494
int
 
495
from_hexadecimal (string s) {
 
496
  int i, n= N(s), res= 0;
 
497
  if ((n>0) && (s[0]=='-'))
 
498
    return -from_hexadecimal (s (1, n));
 
499
  for (i=0; i<n; i++) {
 
500
    res= res << 4;
 
501
    if ((s[i] >= '0') && (s[i] <= '9')) res += (int) (s[i] - '0');
 
502
    if ((s[i] >= 'A') && (s[i] <= 'F')) res += (int) (s[i] + 10 - 'A');
 
503
    if ((s[i] >= 'a') && (s[i] <= 'f')) res += (int) (s[i] + 10 - 'a');
 
504
  }
 
505
  return res;
 
506
}
 
507
 
 
508
/******************************************************************************
 
509
* Convert between verbatim and TeXmacs encoding
 
510
******************************************************************************/
 
511
 
 
512
string
 
513
tm_encode (string s) {
 
514
  register int i;
 
515
  string r;
 
516
  for (i=0; i<N(s); i++) {
 
517
    if (s[i]=='<') r << "<less>";
 
518
    else if (s[i]=='>') r << "<gtr>";
 
519
    else r << s[i];
 
520
  }
 
521
  return r;
 
522
}
 
523
 
 
524
string
 
525
tm_decode (string s) {
 
526
  register int i;
 
527
  string r;
 
528
  for (i=0; i<N(s); i++) {
 
529
    if (s[i]=='<') {
 
530
      register int j;
 
531
      for (j=i+1; j<N(s); j++)
 
532
        if (s[j]=='>') break;
 
533
      if (j<N(s)) j++;
 
534
      if (s(i,j) == "<less>") r << "<";
 
535
      else if (s(i,j) == "<gtr>") r << ">";
 
536
      i=j-1;
 
537
      if (s[i]!='>') return r;
 
538
    }
 
539
    else if (s[i]!='>') r << s[i];
 
540
  }
 
541
  return r;
 
542
}
 
543
 
 
544
string
 
545
tm_correct (string s) {
 
546
  register int i;
 
547
  string r;
 
548
  for (i=0; i<N(s); i++) {
 
549
    if (s[i]=='<') {
 
550
      register bool flag= true;
 
551
      register int j, k;
 
552
      for (j=i+1; j<N(s); j++)
 
553
        if (s[j]=='>') break;
 
554
      if (j==N(s)) return r;
 
555
      for (k=i+1; k<j; k++)
 
556
        if (s[k]=='<') flag= false;
 
557
      if (flag) r << s(i,j+1);
 
558
      i=j;
 
559
    }
 
560
    else if (s[i]!='>') r << s[i];
 
561
  }
 
562
  return r;
 
563
}
 
564
 
 
565
/******************************************************************************
 
566
* Handling escape characters
 
567
******************************************************************************/
 
568
 
 
569
string
 
570
escape_quotes (string s) {
 
571
  int i, n= N(s);
 
572
  string r;
 
573
  for (i=0; i<n; i++) {
 
574
    if ((s[i] == '\\') || (s[i] == '\"')) r << '\\';
 
575
    r << s[i];
 
576
  }
 
577
  return r;
 
578
}
 
579
 
 
580
string
 
581
escape_generic (string s) {
 
582
  int i, n= N(s);
 
583
  string r;
 
584
  for (i=0; i<n; i++) {
 
585
    if ((s[i] == '\2') || (s[i] == '\5') || (s[i] == '\33')) r << '\33';
 
586
    r << s[i];
 
587
  }
 
588
  return r;
 
589
}
 
590
 
 
591
string
 
592
escape_verbatim (string s) {
 
593
  int i, n= N(s);
 
594
  string r;
 
595
  for (i=0; i<n; i++) {
 
596
    unsigned char c= (unsigned char) s[i];
 
597
    if ((c == '\n') || (c == '\t')) r << ' ';
 
598
    else if (((int) c) >= 32) r << s[i];
 
599
  }
 
600
  return r;
 
601
}
 
602
 
 
603
string
 
604
dos_to_better (string s) {
 
605
  int i, n= N(s);
 
606
  string r;
 
607
  for (i=0; i<n; i++)
 
608
    if (s[i] == '\015');
 
609
    else r << s[i];
 
610
  return r;
 
611
}
 
612
 
 
613
/******************************************************************************
 
614
* Reading input from a string
 
615
******************************************************************************/
 
616
 
 
617
bool
 
618
test (string s, int i, const char* test) {
 
619
  int n= N(s), j=0;
 
620
  while (test[j]!='\0') {
 
621
    if (i>=n) return false;
 
622
    if (s[i]!=test[j]) return false;
 
623
    i++; j++;
 
624
  }
 
625
  return true;
 
626
}
 
627
 
 
628
bool
 
629
test (string s, int i, string test) {
 
630
  int n= N(s), m= N(test), j=0;
 
631
  while (j<m) {
 
632
    if (i>=n) return false;
 
633
    if (s[i]!=test[j]) return false;
 
634
    i++; j++;
 
635
  }
 
636
  return true;
 
637
}
 
638
 
 
639
bool
 
640
starts (string s, const char* what) {
 
641
  return test (s, 0, what);
 
642
}
 
643
 
 
644
bool
 
645
starts (string s, const string what) {
 
646
  return test (s, 0, what);
 
647
}
 
648
 
 
649
bool
 
650
ends (string s, const char* what) {
 
651
  string r ((char*) what);
 
652
  if (N(r) > N(s)) return false;
 
653
  return s (N(s)-N(r), N(s)) == r;
 
654
}
 
655
 
 
656
bool
 
657
ends (string s, const string r) {
 
658
  if (N(r) > N(s)) return false;
 
659
  return s (N(s)-N(r), N(s)) == r;
 
660
}
 
661
 
 
662
bool
 
663
read (string s, int& i, const char* test) {
 
664
  int n= N(s), j=0, k=i;
 
665
  while (test[j]!='\0') {
 
666
    if (k>=n) return false;
 
667
    if (s[k]!=test[j]) return false;
 
668
    j++; k++;
 
669
  }
 
670
  i=k;
 
671
  return true;
 
672
}
 
673
 
 
674
bool
 
675
read (string s, int& i, string test) {
 
676
  int n= N(s), m= N(test), j=0, k=i;
 
677
  while (j<m) {
 
678
    if (k>=n) return false;
 
679
    if (s[k]!=test[j]) return false;
 
680
    j++; k++;
 
681
  }
 
682
  i=k;
 
683
  return true;
 
684
}
 
685
 
 
686
bool
 
687
read_line (string s, int& i, string& result) {
 
688
  int start= i;
 
689
  for (; i<N(s); i++) {
 
690
    if (s[i]=='\n') {
 
691
      result= s(start,i++);
 
692
      return true;
 
693
    }
 
694
  }
 
695
  result= s(start,i);
 
696
  return false;
 
697
}
 
698
 
 
699
bool
 
700
read_int (string s, int& i, int& result) {
 
701
  int n= N(s), start= i;
 
702
  result= 0;
 
703
  if (i==n) return false;
 
704
  if (s[i]=='-') {
 
705
    if (i+1==n) return false;
 
706
    if (!is_digit (s[i+1])) return false;
 
707
    i++;
 
708
  }
 
709
  else if (!is_digit (s[i])) return false;
 
710
  while ((i<n) && is_digit (s[i])) i++;
 
711
  result= as_int (s(start,i));
 
712
  return true;
 
713
}
 
714
 
 
715
bool
 
716
read_double (string s, int& i, double& result) {
 
717
  int n= N(s), start= i;
 
718
  result= 0.0;
 
719
  if (i==n) return false;
 
720
  if (s[i]=='-') {
 
721
    if (i+1==n) return false;
 
722
    if (!is_numeric (s[i+1])) return false;
 
723
    i++;
 
724
  }
 
725
  else if (!is_numeric (s[i])) return false;
 
726
  while ((i<n) && is_digit (s[i])) i++;
 
727
  if ((i<n) && (s[i]=='.')) i++;
 
728
  while ((i<n) && is_digit (s[i])) i++;
 
729
  if ((i<n) && ((s[i]=='e') || (s[i]=='E'))) {
 
730
    i++;
 
731
    if ((i<n) && (s[i]=='-')) i++;
 
732
    if ((i==n) || (!is_digit (s[i]))) { i=start; return false; }
 
733
    while ((i<n) && is_digit (s[i])) i++;
 
734
  }
 
735
  result= as_double (s(start,i));
 
736
  return true;
 
737
}
 
738
 
 
739
void
 
740
skip_spaces (string s, int& i) {
 
741
  int n=N(s);
 
742
  while ((i<n) && ((s[i]==' ') || (s[i]=='\t'))) i++;
 
743
}
 
744
 
 
745
void
 
746
skip_line (string s, int& i) {
 
747
  int n=N(s);
 
748
  while ((i<n) && (s[i]!='\n')) i++;
 
749
  if (i<n) i++;
 
750
}
 
751
 
 
752
void
 
753
skip_symbol (string s, int& i) {
 
754
  int n=N(s);
 
755
  if (i<n) {
 
756
    if (s[i]=='<') {
 
757
      for (i++; i<n; i++)
 
758
        if (s[i-1]=='>') break;
 
759
    }
 
760
    else i++;
 
761
  }
 
762
}
 
763
 
 
764
/******************************************************************************
 
765
* Parsing binary data
 
766
******************************************************************************/
 
767
 
 
768
void
 
769
parse (string s, int& pos, QI& ret) {
 
770
  ret= (QI) s[pos++];
 
771
}
 
772
 
 
773
void
 
774
parse (string s, int& pos, QN& ret) {
 
775
  ret= (QN) s[pos++];
 
776
}
 
777
 
 
778
void
 
779
parse (string s, int& pos, HI& ret) {
 
780
  QI c1= (QI) s[pos++];
 
781
  QN c2= (QN) s[pos++];
 
782
  ret= (((HI) c1)<<8)+ c2;
 
783
}
 
784
 
 
785
void
 
786
parse (string s, int& pos, HN& ret) {
 
787
  QN c1= (QN) s[pos++];
 
788
  QN c2= (QN) s[pos++];
 
789
  ret= (((HN) c1)<<8)+ c2;
 
790
}
 
791
 
 
792
void
 
793
parse (string s, int& pos, SI& ret) {
 
794
  QI c1= (QI) s[pos++];
 
795
  QN c2= (QN) s[pos++];
 
796
  QN c3= (QN) s[pos++];
 
797
  QN c4= (QN) s[pos++];
 
798
  ret= (((((((SI) c1)<<8)+ ((SI) c2))<<8)+ ((SI) c3))<<8)+ c4;
 
799
}
 
800
 
 
801
void
 
802
parse (string s, int& pos, SI*& a, int len) {
 
803
  int i;
 
804
  a= new int[len];
 
805
  for (i=0; i<len; i++) parse (s, pos, a[i]);
 
806
}
 
807
 
 
808
/******************************************************************************
 
809
* Searching, replacing and pattern matching
 
810
******************************************************************************/
 
811
 
 
812
int
 
813
search_forwards (string s, int pos, string in) {
 
814
  int k= N(s), n= N(in);
 
815
  while (pos+k <= n) {
 
816
    if (test (in, pos, s)) return pos;
 
817
    pos++;
 
818
  }
 
819
  return -1;
 
820
}
 
821
 
 
822
int
 
823
search_forwards (string s, string in) {
 
824
  return search_forwards (s, 0, in);
 
825
}
 
826
 
 
827
int
 
828
search_backwards (string s, int pos, string in) {
 
829
  while (pos >= 0) {
 
830
    if (test (in, pos, s)) return pos;
 
831
    pos--;
 
832
  }
 
833
  return -1;
 
834
}
 
835
 
 
836
int
 
837
search_backwards (string s, string in) {
 
838
  return search_backwards (s, N(in)-N(s), in);
 
839
}
 
840
 
 
841
string
 
842
replace (string s, string what, string by) {
 
843
  int i, n= N(s);
 
844
  string r;
 
845
  for (i=0; i<n; )
 
846
    if (test (s, i, what)) {
 
847
      r << by;
 
848
      i += N(what);
 
849
    }
 
850
    else {
 
851
      r << s[i];
 
852
      i++;
 
853
    }
 
854
  return r;
 
855
}
 
856
 
 
857
static bool
 
858
match_wildcard (string s, int spos, string w, int wpos) {
 
859
  if (wpos == N(w)) return spos == N(s);
 
860
  if (w[wpos] != '*')
 
861
    return (spos < N(s)) && (s[spos] == w[wpos]) &&
 
862
      match_wildcard (s, spos+1, w, wpos+1);
 
863
  while ((wpos<N(w)) && (w[wpos]=='*')) wpos++;
 
864
  while (spos <= N(s)) {
 
865
    if (match_wildcard (s, spos, w, wpos)) return true;
 
866
    spos++;
 
867
  }
 
868
  return false;
 
869
}
 
870
 
 
871
bool
 
872
match_wildcard (string s, string w) {
 
873
  return match_wildcard (s, 0, w, 0);
 
874
}