~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/goo/GooString.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//
 
3
// GooString.cc
 
4
//
 
5
// Simple variable-length string type.
 
6
//
 
7
// Copyright 1996-2003 Glyph & Cog, LLC
 
8
//
 
9
//========================================================================
 
10
 
 
11
//========================================================================
 
12
//
 
13
// Modified under the Poppler project - http://poppler.freedesktop.org
 
14
//
 
15
// All changes made under the Poppler project to this file are licensed
 
16
// under GPL version 2 or later
 
17
//
 
18
// Copyright (C) 2006 Kristian HĆøgsberg <krh@redhat.com>
 
19
// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 
20
// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
 
21
// Copyright (C) 2008-2011 Albert Astals Cid <aacid@kde.org>
 
22
//
 
23
// To see a description of the changes please see the Changelog file that
 
24
// came with your tarball or type make ChangeLog if you are building from git
 
25
//
 
26
//========================================================================
 
27
 
 
28
#include <config.h>
 
29
 
 
30
#ifdef USE_GCC_PRAGMAS
 
31
#pragma implementation
 
32
#endif
 
33
 
 
34
#include <stdlib.h>
 
35
#include <stddef.h>
 
36
#include <string.h>
 
37
#include <ctype.h>
 
38
#include <assert.h>
 
39
#include <math.h>
 
40
#include "gmem.h"
 
41
#include "GooString.h"
 
42
 
 
43
static const int MAXIMUM_DOUBLE_PREC = 16;
 
44
 
 
45
//------------------------------------------------------------------------
 
46
 
 
47
union GooStringFormatArg {
 
48
  int i;
 
49
  Guint ui;
 
50
  long l;
 
51
  Gulong ul;
 
52
  double f;
 
53
  char c;
 
54
  char *s;
 
55
  GooString *gs;
 
56
};
 
57
 
 
58
enum GooStringFormatType {
 
59
  fmtIntDecimal,
 
60
  fmtIntHex,
 
61
  fmtIntOctal,
 
62
  fmtIntBinary,
 
63
  fmtUIntDecimal,
 
64
  fmtUIntHex,
 
65
  fmtUIntOctal,
 
66
  fmtUIntBinary,
 
67
  fmtLongDecimal,
 
68
  fmtLongHex,
 
69
  fmtLongOctal,
 
70
  fmtLongBinary,
 
71
  fmtULongDecimal,
 
72
  fmtULongHex,
 
73
  fmtULongOctal,
 
74
  fmtULongBinary,
 
75
  fmtDouble,
 
76
  fmtDoubleTrimSmallAware,
 
77
  fmtDoubleTrim,
 
78
  fmtChar,
 
79
  fmtString,
 
80
  fmtGooString,
 
81
  fmtSpace
 
82
};
 
83
 
 
84
static char *formatStrings[] = {
 
85
  "d", "x", "o", "b", "ud", "ux", "uo", "ub",
 
86
  "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
 
87
  "f", "gs", "g",
 
88
  "c",
 
89
  "s",
 
90
  "t",
 
91
  "w",
 
92
  NULL
 
93
};
 
94
 
 
95
//------------------------------------------------------------------------
 
96
 
 
97
int inline GooString::roundedSize(int len) {
 
98
  int delta;
 
99
  if (len <= STR_STATIC_SIZE-1)
 
100
      return STR_STATIC_SIZE;
 
101
  delta = len < 256 ? 7 : 255;
 
102
  return ((len + 1) + delta) & ~delta;
 
103
}
 
104
 
 
105
// Make sure that the buffer is big enough to contain <newLength> characters
 
106
// plus terminating 0.
 
107
// We assume that if this is being called from the constructor, <s> was set
 
108
// to NULL and <length> was set to 0 to indicate unused string before calling us.
 
109
void inline GooString::resize(int newLength) {
 
110
  char *s1 = s;
 
111
 
 
112
  if (!s || (roundedSize(length) != roundedSize(newLength))) {
 
113
    // requires re-allocating data for string
 
114
    if (newLength < STR_STATIC_SIZE) {
 
115
      s1 = sStatic;
 
116
    } else {
 
117
      // allocate a rounded amount
 
118
      if (s == sStatic)
 
119
        s1 = (char*)gmalloc(roundedSize(newLength));
 
120
      else
 
121
        s1 = (char*)grealloc(s, roundedSize(newLength));
 
122
    }
 
123
    if (s == sStatic || s1 == sStatic) {
 
124
      // copy the minimum, we only need to if are moving to or
 
125
      // from sStatic.
 
126
      // assert(s != s1) the roundedSize condition ensures this
 
127
      if (newLength < length) {
 
128
        memcpy(s1, s, newLength);
 
129
      } else {
 
130
        memcpy(s1, s, length);
 
131
      }
 
132
    }
 
133
 
 
134
  }
 
135
 
 
136
  s = s1;
 
137
  length = newLength;
 
138
  s[length] = '\0';
 
139
}
 
140
 
 
141
GooString* GooString::Set(const char *s1, int s1Len, const char *s2, int s2Len)
 
142
{
 
143
    int newLen = 0;
 
144
    char *p;
 
145
 
 
146
    if (s1) {
 
147
        if (CALC_STRING_LEN == s1Len) {
 
148
            s1Len = strlen(s1);
 
149
        } else
 
150
            assert(s1Len >= 0);
 
151
        newLen += s1Len;
 
152
    }
 
153
 
 
154
    if (s2) {
 
155
        if (CALC_STRING_LEN == s2Len) {
 
156
            s2Len = strlen(s2);
 
157
        } else
 
158
            assert(s2Len >= 0);
 
159
        newLen += s2Len;
 
160
    }
 
161
 
 
162
    resize(newLen);
 
163
    p = s;
 
164
    if (s1) {
 
165
        memcpy(p, s1, s1Len);
 
166
        p += s1Len;
 
167
    }
 
168
    if (s2) {
 
169
        memcpy(p, s2, s2Len);
 
170
        p += s2Len;
 
171
    }
 
172
    return this;
 
173
}
 
174
 
 
175
GooString::GooString() {
 
176
  s = NULL;
 
177
  length = 0;
 
178
  Set(NULL);
 
179
}
 
180
 
 
181
GooString::GooString(const char *sA) {
 
182
  s = NULL;
 
183
  length = 0;
 
184
  Set(sA, CALC_STRING_LEN);
 
185
}
 
186
 
 
187
GooString::GooString(const char *sA, int lengthA) {
 
188
  s = NULL;
 
189
  length = 0;
 
190
  Set(sA, lengthA);
 
191
}
 
192
 
 
193
GooString::GooString(GooString *str, int idx, int lengthA) {
 
194
  s = NULL;
 
195
  length = 0;
 
196
  assert(idx + lengthA <= str->length);
 
197
  Set(str->getCString() + idx, lengthA);
 
198
}
 
199
 
 
200
GooString::GooString(const GooString *str) {
 
201
  s = NULL;
 
202
  length = 0;
 
203
  Set(str->getCString(), str->length);
 
204
}
 
205
 
 
206
GooString::GooString(GooString *str1, GooString *str2) {
 
207
  s = NULL;
 
208
  length = 0;
 
209
  Set(str1->getCString(), str1->length, str2->getCString(), str2->length);
 
210
}
 
211
 
 
212
GooString *GooString::fromInt(int x) {
 
213
  char buf[24]; // enough space for 64-bit ints plus a little extra
 
214
  char *p;
 
215
  int len;
 
216
  formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len);
 
217
  return new GooString(p, len);
 
218
}
 
219
 
 
220
GooString *GooString::format(char *fmt, ...) {
 
221
  va_list argList;
 
222
  GooString *s;
 
223
 
 
224
  s = new GooString();
 
225
  va_start(argList, fmt);
 
226
  s->appendfv(fmt, argList);
 
227
  va_end(argList);
 
228
  return s;
 
229
}
 
230
 
 
231
GooString *GooString::formatv(char *fmt, va_list argList) {
 
232
  GooString *s;
 
233
 
 
234
  s = new GooString();
 
235
  s->appendfv(fmt, argList);
 
236
  return s;
 
237
}
 
238
 
 
239
GooString::~GooString() {
 
240
  if (s != sStatic)
 
241
    gfree(s);
 
242
}
 
243
 
 
244
GooString *GooString::clear() {
 
245
  resize(0);
 
246
  return this;
 
247
}
 
248
 
 
249
GooString *GooString::append(char c) {
 
250
  return append((const char*)&c, 1);
 
251
}
 
252
 
 
253
GooString *GooString::append(GooString *str) {
 
254
  return append(str->getCString(), str->getLength());
 
255
}
 
256
 
 
257
GooString *GooString::append(const char *str, int lengthA) {
 
258
  int prevLen = length;
 
259
  if (CALC_STRING_LEN == lengthA)
 
260
    lengthA = strlen(str);
 
261
  resize(length + lengthA);
 
262
  memcpy(s + prevLen, str, lengthA);
 
263
  return this;
 
264
}
 
265
 
 
266
GooString *GooString::appendf(char *fmt, ...) {
 
267
  va_list argList;
 
268
 
 
269
  va_start(argList, fmt);
 
270
  appendfv(fmt, argList);
 
271
  va_end(argList);
 
272
  return this;
 
273
}
 
274
 
 
275
GooString *GooString::appendfv(char *fmt, va_list argList) {
 
276
  GooStringFormatArg *args;
 
277
  int argsLen, argsSize;
 
278
  GooStringFormatArg arg;
 
279
  int idx, width, prec;
 
280
  GBool reverseAlign, zeroFill;
 
281
  GooStringFormatType ft;
 
282
  char buf[65];
 
283
  int len, i;
 
284
  char *p0, *p1, *str;
 
285
 
 
286
  argsLen = 0;
 
287
  argsSize = 8;
 
288
  args = (GooStringFormatArg *)gmallocn(argsSize, sizeof(GooStringFormatArg));
 
289
 
 
290
  p0 = fmt;
 
291
  while (*p0) {
 
292
    if (*p0 == '{') {
 
293
      ++p0;
 
294
      if (*p0 == '{') {
 
295
        ++p0;
 
296
        append('{');
 
297
      } else {
 
298
 
 
299
        // parse the format string
 
300
        if (!(*p0 >= '0' && *p0 <= '9')) {
 
301
          break;
 
302
        }
 
303
        idx = *p0 - '0';
 
304
        for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
 
305
          idx = 10 * idx + (*p0 - '0');
 
306
        }
 
307
        if (*p0 != ':') {
 
308
          break;
 
309
        }
 
310
        ++p0;
 
311
        if (*p0 == '-') {
 
312
          reverseAlign = gTrue;
 
313
          ++p0;
 
314
        } else {
 
315
          reverseAlign = gFalse;
 
316
        }
 
317
        width = 0;
 
318
        zeroFill = *p0 == '0';
 
319
        for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
 
320
          width = 10 * width + (*p0 - '0');
 
321
        }
 
322
        if (*p0 == '.') {
 
323
          ++p0;
 
324
          prec = 0;
 
325
          for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
 
326
            prec = 10 * prec + (*p0 - '0');
 
327
          }
 
328
        } else {
 
329
          prec = 0;
 
330
        }
 
331
        for (ft = (GooStringFormatType)0;
 
332
             formatStrings[ft];
 
333
             ft = (GooStringFormatType)(ft + 1)) {
 
334
          if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
 
335
            break;
 
336
          }
 
337
        }
 
338
        if (!formatStrings[ft]) {
 
339
          break;
 
340
        }
 
341
        p0 += strlen(formatStrings[ft]);
 
342
        if (*p0 != '}') {
 
343
          break;
 
344
        }
 
345
        ++p0;
 
346
 
 
347
        // fetch the argument
 
348
        if (idx > argsLen) {
 
349
          break;
 
350
        }
 
351
        if (idx == argsLen) {
 
352
          if (argsLen == argsSize) {
 
353
            argsSize *= 2;
 
354
            args = (GooStringFormatArg *)greallocn(args, argsSize,
 
355
                                                 sizeof(GooStringFormatArg));
 
356
          }
 
357
          switch (ft) {
 
358
          case fmtIntDecimal:
 
359
          case fmtIntHex:
 
360
          case fmtIntOctal:
 
361
          case fmtIntBinary:
 
362
          case fmtSpace:
 
363
            args[argsLen].i = va_arg(argList, int);
 
364
            break;
 
365
          case fmtUIntDecimal:
 
366
          case fmtUIntHex:
 
367
          case fmtUIntOctal:
 
368
          case fmtUIntBinary:
 
369
            args[argsLen].ui = va_arg(argList, Guint);
 
370
            break;
 
371
          case fmtLongDecimal:
 
372
          case fmtLongHex:
 
373
          case fmtLongOctal:
 
374
          case fmtLongBinary:
 
375
            args[argsLen].l = va_arg(argList, long);
 
376
            break;
 
377
          case fmtULongDecimal:
 
378
          case fmtULongHex:
 
379
          case fmtULongOctal:
 
380
          case fmtULongBinary:
 
381
            args[argsLen].ul = va_arg(argList, Gulong);
 
382
            break;
 
383
          case fmtDouble:
 
384
          case fmtDoubleTrim:
 
385
          case fmtDoubleTrimSmallAware:
 
386
            args[argsLen].f = va_arg(argList, double);
 
387
            break;
 
388
          case fmtChar:
 
389
            args[argsLen].c = (char)va_arg(argList, int);
 
390
            break;
 
391
          case fmtString:
 
392
            args[argsLen].s = va_arg(argList, char *);
 
393
            break;
 
394
          case fmtGooString:
 
395
            args[argsLen].gs = va_arg(argList, GooString *);
 
396
            break;
 
397
          }
 
398
          ++argsLen;
 
399
        }
 
400
 
 
401
        // format the argument
 
402
        arg = args[idx];
 
403
        switch (ft) {
 
404
        case fmtIntDecimal:
 
405
          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
 
406
          break;
 
407
        case fmtIntHex:
 
408
          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
 
409
          break;
 
410
        case fmtIntOctal:
 
411
          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
 
412
          break;
 
413
        case fmtIntBinary:
 
414
          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
 
415
          break;
 
416
        case fmtUIntDecimal:
 
417
          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10,
 
418
                     &str, &len);
 
419
          break;
 
420
        case fmtUIntHex:
 
421
          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16,
 
422
                     &str, &len);
 
423
          break;
 
424
        case fmtUIntOctal:
 
425
          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
 
426
          break;
 
427
        case fmtUIntBinary:
 
428
          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
 
429
          break;
 
430
        case fmtLongDecimal:
 
431
          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
 
432
          break;
 
433
        case fmtLongHex:
 
434
          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
 
435
          break;
 
436
        case fmtLongOctal:
 
437
          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
 
438
          break;
 
439
        case fmtLongBinary:
 
440
          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
 
441
          break;
 
442
        case fmtULongDecimal:
 
443
          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10,
 
444
                     &str, &len);
 
445
          break;
 
446
        case fmtULongHex:
 
447
          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16,
 
448
                     &str, &len);
 
449
          break;
 
450
        case fmtULongOctal:
 
451
          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
 
452
          break;
 
453
        case fmtULongBinary:
 
454
          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
 
455
          break;
 
456
        case fmtDouble:
 
457
          formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
 
458
          break;
 
459
        case fmtDoubleTrim:
 
460
          formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
 
461
          break;
 
462
        case fmtDoubleTrimSmallAware:
 
463
          formatDoubleSmallAware(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
 
464
          break;
 
465
        case fmtChar:
 
466
          buf[0] = arg.c;
 
467
          str = buf;
 
468
          len = 1;
 
469
          reverseAlign = !reverseAlign;
 
470
          break;
 
471
        case fmtString:
 
472
          str = arg.s;
 
473
          len = strlen(str);
 
474
          reverseAlign = !reverseAlign;
 
475
          break;
 
476
        case fmtGooString:
 
477
          str = arg.gs->getCString();
 
478
          len = arg.gs->getLength();
 
479
          reverseAlign = !reverseAlign;
 
480
          break;
 
481
        case fmtSpace:
 
482
          str = buf;
 
483
          len = 0;
 
484
          width = arg.i;
 
485
          break;
 
486
        }
 
487
 
 
488
        // append the formatted arg, handling width and alignment
 
489
        if (!reverseAlign && len < width) {
 
490
          for (i = len; i < width; ++i) {
 
491
            append(' ');
 
492
          }
 
493
        }
 
494
        append(str, len);
 
495
        if (reverseAlign && len < width) {
 
496
          for (i = len; i < width; ++i) {
 
497
            append(' ');
 
498
          }
 
499
        }
 
500
      }
 
501
 
 
502
    } else if (*p0 == '}') {
 
503
      ++p0;
 
504
      if (*p0 == '}') {
 
505
        ++p0;
 
506
      }
 
507
      append('}');
 
508
      
 
509
    } else {
 
510
      for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ;
 
511
      append(p0, p1 - p0);
 
512
      p0 = p1;
 
513
    }
 
514
  }
 
515
 
 
516
  gfree(args);
 
517
  return this;
 
518
}
 
519
 
 
520
void GooString::formatInt(long x, char *buf, int bufSize,
 
521
                        GBool zeroFill, int width, int base,
 
522
                        char **p, int *len) {
 
523
  static char vals[17] = "0123456789abcdef";
 
524
  GBool neg;
 
525
  int start, i, j;
 
526
 
 
527
  i = bufSize;
 
528
  if ((neg = x < 0)) {
 
529
    x = -x;
 
530
  }
 
531
  start = neg ? 1 : 0;
 
532
  if (x == 0) {
 
533
    buf[--i] = '0';
 
534
  } else {
 
535
    while (i > start && x) {
 
536
      buf[--i] = vals[x % base];
 
537
      x /= base;
 
538
    }
 
539
  }
 
540
  if (zeroFill) {
 
541
    for (j = bufSize - i; i > start && j < width - start; ++j) {
 
542
      buf[--i] = '0';
 
543
    }
 
544
  }
 
545
  if (neg) {
 
546
    buf[--i] = '-';
 
547
  }
 
548
  *p = buf + i;
 
549
  *len = bufSize - i;
 
550
}
 
551
 
 
552
void GooString::formatUInt(Gulong x, char *buf, int bufSize,
 
553
                         GBool zeroFill, int width, int base,
 
554
                         char **p, int *len) {
 
555
  static char vals[17] = "0123456789abcdef";
 
556
  int i, j;
 
557
 
 
558
  i = bufSize;
 
559
  if (x == 0) {
 
560
    buf[--i] = '0';
 
561
  } else {
 
562
    while (i > 0 && x) {
 
563
      buf[--i] = vals[x % base];
 
564
      x /= base;
 
565
    }
 
566
  }
 
567
  if (zeroFill) {
 
568
    for (j = bufSize - i; i > 0 && j < width; ++j) {
 
569
      buf[--i] = '0';
 
570
    }
 
571
  }
 
572
  *p = buf + i;
 
573
  *len = bufSize - i;
 
574
}
 
575
 
 
576
void GooString::formatDouble(double x, char *buf, int bufSize, int prec,
 
577
                           GBool trim, char **p, int *len) {
 
578
  GBool neg, started;
 
579
  double x2;
 
580
  int d, i, j;
 
581
 
 
582
  if ((neg = x < 0)) {
 
583
    x = -x;
 
584
  }
 
585
  x = floor(x * pow((double)10, prec) + 0.5);
 
586
  i = bufSize;
 
587
  started = !trim;
 
588
  for (j = 0; j < prec && i > 1; ++j) {
 
589
    x2 = floor(0.1 * (x + 0.5));
 
590
    d = (int)floor(x - 10 * x2 + 0.5);
 
591
    if (started || d != 0) {
 
592
      buf[--i] = '0' + d;
 
593
      started = gTrue;
 
594
    }
 
595
    x = x2;
 
596
  }
 
597
  if (i > 1 && started) {
 
598
    buf[--i] = '.';
 
599
  }
 
600
  if (i > 1) {
 
601
    do {
 
602
      x2 = floor(0.1 * (x + 0.5));
 
603
      d = (int)floor(x - 10 * x2 + 0.5);
 
604
      buf[--i] = '0' + d;
 
605
      x = x2;
 
606
    } while (i > 1 && x);
 
607
  }
 
608
  if (neg) {
 
609
    buf[--i] = '-';
 
610
  }
 
611
  *p = buf + i;
 
612
  *len = bufSize - i;
 
613
}
 
614
 
 
615
void GooString::formatDoubleSmallAware(double x, char *buf, int bufSize, int prec,
 
616
                                      GBool trim, char **p, int *len)
 
617
{
 
618
  double absX = fabs(x);
 
619
  if (absX >= 0.1) {
 
620
    formatDouble(x, buf, bufSize, prec, trim, p, len);
 
621
  } else {
 
622
    while (absX < 0.1 && prec < MAXIMUM_DOUBLE_PREC)
 
623
    {
 
624
      absX = absX * 10;
 
625
      prec++;
 
626
    }
 
627
    formatDouble(x, buf, bufSize, prec, trim, p, len);
 
628
  }
 
629
}
 
630
 
 
631
GooString *GooString::insert(int i, char c) {
 
632
  return insert(i, (const char*)&c, 1);
 
633
}
 
634
 
 
635
GooString *GooString::insert(int i, GooString *str) {
 
636
  return insert(i, str->getCString(), str->getLength());
 
637
}
 
638
 
 
639
GooString *GooString::insert(int i, const char *str, int lengthA) {
 
640
  int j;
 
641
  int prevLen = length;
 
642
  if (CALC_STRING_LEN == lengthA)
 
643
    lengthA = strlen(str);
 
644
 
 
645
  resize(length + lengthA);
 
646
  for (j = prevLen; j >= i; --j)
 
647
    s[j+lengthA] = s[j];
 
648
  memcpy(s+i, str, lengthA);
 
649
  return this;
 
650
}
 
651
 
 
652
GooString *GooString::del(int i, int n) {
 
653
  int j;
 
654
 
 
655
  if (n > 0) {
 
656
    if (i + n > length) {
 
657
      n = length - i;
 
658
    }
 
659
    for (j = i; j <= length - n; ++j) {
 
660
      s[j] = s[j + n];
 
661
    }
 
662
    resize(length - n);
 
663
  }
 
664
  return this;
 
665
}
 
666
 
 
667
GooString *GooString::upperCase() {
 
668
  int i;
 
669
 
 
670
  for (i = 0; i < length; ++i) {
 
671
    if (islower(s[i]))
 
672
      s[i] = toupper(s[i]);
 
673
  }
 
674
  return this;
 
675
}
 
676
 
 
677
GooString *GooString::lowerCase() {
 
678
  int i;
 
679
 
 
680
  for (i = 0; i < length; ++i) {
 
681
    if (isupper(s[i]))
 
682
      s[i] = tolower(s[i]);
 
683
  }
 
684
  return this;
 
685
}
 
686
 
 
687
int GooString::cmp(GooString *str) const {
 
688
  int n1, n2, i, x;
 
689
  char *p1, *p2;
 
690
 
 
691
  n1 = length;
 
692
  n2 = str->length;
 
693
  for (i = 0, p1 = s, p2 = str->s; i < n1 && i < n2; ++i, ++p1, ++p2) {
 
694
    x = *p1 - *p2;
 
695
    if (x != 0) {
 
696
      return x;
 
697
    }
 
698
  }
 
699
  return n1 - n2;
 
700
}
 
701
 
 
702
int GooString::cmpN(GooString *str, int n) const {
 
703
  int n1, n2, i, x;
 
704
  char *p1, *p2;
 
705
 
 
706
  n1 = length;
 
707
  n2 = str->length;
 
708
  for (i = 0, p1 = s, p2 = str->s;
 
709
       i < n1 && i < n2 && i < n;
 
710
       ++i, ++p1, ++p2) {
 
711
    x = *p1 - *p2;
 
712
    if (x != 0) {
 
713
      return x;
 
714
    }
 
715
  }
 
716
  if (i == n) {
 
717
    return 0;
 
718
  }
 
719
  return n1 - n2;
 
720
}
 
721
 
 
722
int GooString::cmp(const char *sA) const {
 
723
  int n1, i, x;
 
724
  const char *p1, *p2;
 
725
 
 
726
  n1 = length;
 
727
  for (i = 0, p1 = s, p2 = sA; i < n1 && *p2; ++i, ++p1, ++p2) {
 
728
    x = *p1 - *p2;
 
729
    if (x != 0) {
 
730
      return x;
 
731
    }
 
732
  }
 
733
  if (i < n1) {
 
734
    return 1;
 
735
  }
 
736
  if (*p2) {
 
737
    return -1;
 
738
  }
 
739
  return 0;
 
740
}
 
741
 
 
742
int GooString::cmpN(const char *sA, int n) const {
 
743
  int n1, i, x;
 
744
  const char *p1, *p2;
 
745
 
 
746
  n1 = length;
 
747
  for (i = 0, p1 = s, p2 = sA; i < n1 && *p2 && i < n; ++i, ++p1, ++p2) {
 
748
    x = *p1 - *p2;
 
749
    if (x != 0) {
 
750
      return x;
 
751
    }
 
752
  }
 
753
  if (i == n) {
 
754
    return 0;
 
755
  }
 
756
  if (i < n1) {
 
757
    return 1;
 
758
  }
 
759
  if (*p2) {
 
760
    return -1;
 
761
  }
 
762
  return 0;
 
763
}
 
764
 
 
765
GBool GooString::hasUnicodeMarker(void)
 
766
{
 
767
    return (s[0] & 0xff) == 0xfe && (s[1] & 0xff) == 0xff;
 
768
}
 
769
 
 
770
GooString *GooString::sanitizedName(GBool psmode)
 
771
{
 
772
  GooString *name;
 
773
  char buf[8];
 
774
  int i;
 
775
  char c;
 
776
 
 
777
  name = new GooString();
 
778
 
 
779
  if (psmode)
 
780
  {
 
781
    // ghostscript chokes on names that begin with out-of-limits
 
782
    // numbers, e.g., 1e4foo is handled correctly (as a name), but
 
783
    // 1e999foo generates a limitcheck error
 
784
    c = getChar(0);
 
785
    if (c >= '0' && c <= '9') {
 
786
      name->append('f');
 
787
    }
 
788
  }
 
789
 
 
790
  for (i = 0; i < getLength(); ++i) {
 
791
    c = getChar(i);
 
792
    if (c <= (char)0x20 || c >= (char)0x7f ||
 
793
        c == ' ' ||
 
794
        c == '(' || c == ')' || c == '<' || c == '>' ||
 
795
        c == '[' || c == ']' || c == '{' || c == '}' ||
 
796
        c == '/' || c == '%' || c == '#') {
 
797
      sprintf(buf, "#%02x", c & 0xff);
 
798
      name->append(buf);
 
799
    } else {
 
800
      name->append(c);
 
801
    }
 
802
  }
 
803
  return name;
 
804
}