1/***************************************************************************/
2/*                                                                         */
3/*  psconv.c                                                               */
4/*                                                                         */
5/*    Some convenience conversions (body).                                 */
6/*                                                                         */
7/*  Copyright 2006, 2008, 2009, 2012-2013 by                               */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19#include <ft2build.h>
20#include FT_INTERNAL_POSTSCRIPT_AUX_H
21#include FT_INTERNAL_DEBUG_H
22
23#include "psconv.h"
24#include "psauxerr.h"
25
26
27  /*************************************************************************/
28  /*                                                                       */
29  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
30  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
31  /* messages during execution.                                            */
32  /*                                                                       */
33#undef  FT_COMPONENT
34#define FT_COMPONENT  trace_psconv
35
36
37  /* The following array is used by various functions to quickly convert */
38  /* digits (both decimal and non-decimal) into numbers.                 */
39
40#if 'A' == 65
41  /* ASCII */
42
43  static const FT_Char  ft_char_table[128] =
44  {
45    /* 0x00 */
46    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
48    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
49     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
50    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
51    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
52    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
53    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
54  };
55
56  /* no character >= 0x80 can represent a valid number */
57#define OP  >=
58
59#endif /* 'A' == 65 */
60
61#if 'A' == 193
62  /* EBCDIC */
63
64  static const FT_Char  ft_char_table[128] =
65  {
66    /* 0x80 */
67    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
68    -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
69    -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
70    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
72    -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
73    -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
74     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
75  };
76
77  /* no character < 0x80 can represent a valid number */
78#define OP  <
79
80#endif /* 'A' == 193 */
81
82
83  FT_LOCAL_DEF( FT_Long )
84  PS_Conv_Strtol( FT_Byte**  cursor,
85                  FT_Byte*   limit,
86                  FT_Long    base )
87  {
88    FT_Byte*  p = *cursor;
89
90    FT_Long   num           = 0;
91    FT_Bool   sign          = 0;
92    FT_Bool   have_overflow = 0;
93
94    FT_Long   num_limit;
95    FT_Char   c_limit;
96
97
98    if ( p >= limit )
99      goto Bad;
100
101    if ( base < 2 || base > 36 )
102    {
103      FT_TRACE4(( "!!!INVALID BASE:!!!" ));
104      return 0;
105    }
106
107    if ( *p == '-' || *p == '+' )
108    {
109      sign = FT_BOOL( *p == '-' );
110
111      p++;
112      if ( p == limit )
113        goto Bad;
114    }
115
116    num_limit = 0x7FFFFFFFL / base;
117    c_limit   = (FT_Char)( 0x7FFFFFFFL % base );
118
119    for ( ; p < limit; p++ )
120    {
121      FT_Char  c;
122
123
124      if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
125        break;
126
127      c = ft_char_table[*p & 0x7f];
128
129      if ( c < 0 || c >= base )
130        break;
131
132      if ( num > num_limit || ( num == num_limit && c > c_limit ) )
133        have_overflow = 1;
134      else
135        num = num * base + c;
136    }
137
138    *cursor = p;
139
140    if ( have_overflow )
141    {
142      num = 0x7FFFFFFFL;
143      FT_TRACE4(( "!!!OVERFLOW:!!!" ));
144    }
145
146    if ( sign )
147      num = -num;
148
149    return num;
150
151  Bad:
152    FT_TRACE4(( "!!!END OF DATA:!!!" ));
153    return 0;
154  }
155
156
157  FT_LOCAL_DEF( FT_Long )
158  PS_Conv_ToInt( FT_Byte**  cursor,
159                 FT_Byte*   limit )
160
161  {
162    FT_Byte*  p = *cursor;
163    FT_Byte*  curp;
164
165    FT_Long   num;
166
167
168    curp = p;
169    num  = PS_Conv_Strtol( &p, limit, 10 );
170
171    if ( p == curp )
172      return 0;
173
174    if ( p < limit && *p == '#' )
175    {
176      p++;
177
178      curp = p;
179      num  = PS_Conv_Strtol( &p, limit, num );
180
181      if ( p == curp )
182        return 0;
183    }
184
185    *cursor = p;
186
187    return num;
188  }
189
190
191  FT_LOCAL_DEF( FT_Fixed )
192  PS_Conv_ToFixed( FT_Byte**  cursor,
193                   FT_Byte*   limit,
194                   FT_Long    power_ten )
195  {
196    FT_Byte*  p = *cursor;
197    FT_Byte*  curp;
198
199    FT_Fixed  integral = 0;
200    FT_Long   decimal  = 0;
201    FT_Long   divider  = 1;
202
203    FT_Bool   sign           = 0;
204    FT_Bool   have_overflow  = 0;
205    FT_Bool   have_underflow = 0;
206
207
208    if ( p >= limit )
209      goto Bad;
210
211    if ( *p == '-' || *p == '+' )
212    {
213      sign = FT_BOOL( *p == '-' );
214
215      p++;
216      if ( p == limit )
217        goto Bad;
218    }
219
220    /* read the integer part */
221    if ( *p != '.' )
222    {
223      curp     = p;
224      integral = PS_Conv_ToInt( &p, limit );
225
226      if ( p == curp )
227        return 0;
228
229      if ( integral > 0x7FFF )
230        have_overflow = 1;
231      else
232        integral = (FT_Fixed)( (FT_UInt32)integral << 16 );
233    }
234
235    /* read the decimal part */
236    if ( p < limit && *p == '.' )
237    {
238      p++;
239
240      for ( ; p < limit; p++ )
241      {
242        FT_Char  c;
243
244
245        if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
246          break;
247
248        c = ft_char_table[*p & 0x7f];
249
250        if ( c < 0 || c >= 10 )
251          break;
252
253        if ( decimal < 0xCCCCCCCL )
254        {
255          decimal = decimal * 10 + c;
256
257          if ( !integral && power_ten > 0 )
258            power_ten--;
259          else
260            divider *= 10;
261        }
262      }
263    }
264
265    /* read exponent, if any */
266    if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
267    {
268      FT_Long  exponent;
269
270
271      p++;
272
273      curp     = p;
274      exponent = PS_Conv_ToInt( &p, limit );
275
276      if ( curp == p )
277        return 0;
278
279      /* arbitrarily limit exponent */
280      if ( exponent > 1000 )
281        have_overflow = 1;
282      else if ( exponent < -1000 )
283        have_underflow = 1;
284      else
285        power_ten += exponent;
286    }
287
288    *cursor = p;
289
290    if ( !integral && !decimal )
291      return 0;
292
293    if ( have_overflow )
294      goto Overflow;
295    if ( have_underflow )
296      goto Underflow;
297
298    while ( power_ten > 0 )
299    {
300      if ( integral >= 0xCCCCCCCL )
301        goto Overflow;
302      integral *= 10;
303
304      if ( decimal >= 0xCCCCCCCL )
305      {
306        if ( divider == 1 )
307          goto Overflow;
308        divider /= 10;
309      }
310      else
311        decimal *= 10;
312
313      power_ten--;
314    }
315
316    while ( power_ten < 0 )
317    {
318      integral /= 10;
319      if ( divider < 0xCCCCCCCL )
320        divider *= 10;
321      else
322        decimal /= 10;
323
324      if ( !integral && !decimal )
325        goto Underflow;
326
327      power_ten++;
328    }
329
330    if ( decimal )
331    {
332      decimal = FT_DivFix( decimal, divider );
333      /* it's not necessary to check this addition for overflow */
334      /* due to the structure of the real number representation */
335      integral += decimal;
336    }
337
338  Exit:
339    if ( sign )
340      integral = -integral;
341
342    return integral;
343
344  Bad:
345    FT_TRACE4(( "!!!END OF DATA:!!!" ));
346    return 0;
347
348  Overflow:
349    integral = 0x7FFFFFFFL;
350    FT_TRACE4(( "!!!OVERFLOW:!!!" ));
351    goto Exit;
352
353  Underflow:
354    FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
355    return 0;
356  }
357
358
359#if 0
360  FT_LOCAL_DEF( FT_UInt )
361  PS_Conv_StringDecode( FT_Byte**  cursor,
362                        FT_Byte*   limit,
363                        FT_Byte*   buffer,
364                        FT_Offset  n )
365  {
366    FT_Byte*  p;
367    FT_UInt   r = 0;
368
369
370    for ( p = *cursor; r < n && p < limit; p++ )
371    {
372      FT_Byte  b;
373
374
375      if ( *p != '\\' )
376      {
377        buffer[r++] = *p;
378
379        continue;
380      }
381
382      p++;
383
384      switch ( *p )
385      {
386      case 'n':
387        b = '\n';
388        break;
389      case 'r':
390        b = '\r';
391        break;
392      case 't':
393        b = '\t';
394        break;
395      case 'b':
396        b = '\b';
397        break;
398      case 'f':
399        b = '\f';
400        break;
401      case '\r':
402        p++;
403        if ( *p != '\n' )
404        {
405          b = *p;
406
407          break;
408        }
409        /* no break */
410      case '\n':
411        continue;
412        break;
413      default:
414        if ( IS_PS_DIGIT( *p ) )
415        {
416          b = *p - '0';
417
418          p++;
419
420          if ( IS_PS_DIGIT( *p ) )
421          {
422            b = b * 8 + *p - '0';
423
424            p++;
425
426            if ( IS_PS_DIGIT( *p ) )
427              b = b * 8 + *p - '0';
428            else
429            {
430              buffer[r++] = b;
431              b = *p;
432            }
433          }
434          else
435          {
436            buffer[r++] = b;
437            b = *p;
438          }
439        }
440        else
441          b = *p;
442        break;
443      }
444
445      buffer[r++] = b;
446    }
447
448    *cursor = p;
449
450    return r;
451  }
452#endif /* 0 */
453
454
455  FT_LOCAL_DEF( FT_UInt )
456  PS_Conv_ASCIIHexDecode( FT_Byte**  cursor,
457                          FT_Byte*   limit,
458                          FT_Byte*   buffer,
459                          FT_Offset  n )
460  {
461    FT_Byte*  p;
462    FT_UInt   r   = 0;
463    FT_UInt   w   = 0;
464    FT_UInt   pad = 0x01;
465
466
467    n *= 2;
468
469#if 1
470
471    p = *cursor;
472
473    if ( p >= limit )
474      return 0;
475
476    if ( n > (FT_UInt)( limit - p ) )
477      n = (FT_UInt)( limit - p );
478
479    /* we try to process two nibbles at a time to be as fast as possible */
480    for ( ; r < n; r++ )
481    {
482      FT_UInt  c = p[r];
483
484
485      if ( IS_PS_SPACE( c ) )
486        continue;
487
488      if ( c OP 0x80 )
489        break;
490
491      c = ft_char_table[c & 0x7F];
492      if ( (unsigned)c >= 16 )
493        break;
494
495      pad = ( pad << 4 ) | c;
496      if ( pad & 0x100 )
497      {
498        buffer[w++] = (FT_Byte)pad;
499        pad         = 0x01;
500      }
501    }
502
503    if ( pad != 0x01 )
504      buffer[w++] = (FT_Byte)( pad << 4 );
505
506    *cursor = p + r;
507
508    return w;
509
510#else /* 0 */
511
512    for ( r = 0; r < n; r++ )
513    {
514      FT_Char  c;
515
516
517      if ( IS_PS_SPACE( *p ) )
518        continue;
519
520      if ( *p OP 0x80 )
521        break;
522
523      c = ft_char_table[*p & 0x7f];
524
525      if ( (unsigned)c >= 16 )
526        break;
527
528      if ( r & 1 )
529      {
530        *buffer = (FT_Byte)(*buffer + c);
531        buffer++;
532      }
533      else
534        *buffer = (FT_Byte)(c << 4);
535
536      r++;
537    }
538
539    *cursor = p;
540
541    return ( r + 1 ) / 2;
542
543#endif /* 0 */
544
545  }
546
547
548  FT_LOCAL_DEF( FT_UInt )
549  PS_Conv_EexecDecode( FT_Byte**   cursor,
550                       FT_Byte*    limit,
551                       FT_Byte*    buffer,
552                       FT_Offset   n,
553                       FT_UShort*  seed )
554  {
555    FT_Byte*  p;
556    FT_UInt   r;
557    FT_UInt   s = *seed;
558
559
560#if 1
561
562    p = *cursor;
563
564    if ( p >= limit )
565      return 0;
566
567    if ( n > (FT_UInt)(limit - p) )
568      n = (FT_UInt)(limit - p);
569
570    for ( r = 0; r < n; r++ )
571    {
572      FT_UInt  val = p[r];
573      FT_UInt  b   = ( val ^ ( s >> 8 ) );
574
575
576      s         = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
577      buffer[r] = (FT_Byte) b;
578    }
579
580    *cursor = p + n;
581    *seed   = (FT_UShort)s;
582
583#else /* 0 */
584
585    for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
586    {
587      FT_Byte  b = (FT_Byte)( *p ^ ( s >> 8 ) );
588
589
590      s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
591      *buffer++ = b;
592    }
593    *cursor = p;
594    *seed   = s;
595
596#endif /* 0 */
597
598    return r;
599  }
600
601
602/* END */
603