• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * psconv.c
4  *
5  *   Some convenience conversions (body).
6  *
7  * Copyright 2006-2018 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 )
PS_Conv_Strtol(FT_Byte ** cursor,FT_Byte * limit,FT_Long base)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       /* only a single sign is allowed */
116       if ( *p == '-' || *p == '+' )
117         return 0;
118     }
119 
120     num_limit = 0x7FFFFFFFL / base;
121     c_limit   = (FT_Char)( 0x7FFFFFFFL % base );
122 
123     for ( ; p < limit; p++ )
124     {
125       FT_Char  c;
126 
127 
128       if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
129         break;
130 
131       c = ft_char_table[*p & 0x7F];
132 
133       if ( c < 0 || c >= base )
134         break;
135 
136       if ( num > num_limit || ( num == num_limit && c > c_limit ) )
137         have_overflow = 1;
138       else
139         num = num * base + c;
140     }
141 
142     *cursor = p;
143 
144     if ( have_overflow )
145     {
146       num = 0x7FFFFFFFL;
147       FT_TRACE4(( "!!!OVERFLOW:!!!" ));
148     }
149 
150     if ( sign )
151       num = -num;
152 
153     return num;
154 
155   Bad:
156     FT_TRACE4(( "!!!END OF DATA:!!!" ));
157     return 0;
158   }
159 
160 
161   FT_LOCAL_DEF( FT_Long )
PS_Conv_ToInt(FT_Byte ** cursor,FT_Byte * limit)162   PS_Conv_ToInt( FT_Byte**  cursor,
163                  FT_Byte*   limit )
164 
165   {
166     FT_Byte*  p = *cursor;
167     FT_Byte*  curp;
168 
169     FT_Long   num;
170 
171 
172     curp = p;
173     num  = PS_Conv_Strtol( &p, limit, 10 );
174 
175     if ( p == curp )
176       return 0;
177 
178     if ( p < limit && *p == '#' )
179     {
180       p++;
181 
182       curp = p;
183       num  = PS_Conv_Strtol( &p, limit, num );
184 
185       if ( p == curp )
186         return 0;
187     }
188 
189     *cursor = p;
190 
191     return num;
192   }
193 
194 
195   FT_LOCAL_DEF( FT_Fixed )
PS_Conv_ToFixed(FT_Byte ** cursor,FT_Byte * limit,FT_Long power_ten)196   PS_Conv_ToFixed( FT_Byte**  cursor,
197                    FT_Byte*   limit,
198                    FT_Long    power_ten )
199   {
200     FT_Byte*  p = *cursor;
201     FT_Byte*  curp;
202 
203     FT_Fixed  integral = 0;
204     FT_Long   decimal  = 0;
205     FT_Long   divider  = 1;
206 
207     FT_Bool   sign           = 0;
208     FT_Bool   have_overflow  = 0;
209     FT_Bool   have_underflow = 0;
210 
211 
212     if ( p >= limit )
213       goto Bad;
214 
215     if ( *p == '-' || *p == '+' )
216     {
217       sign = FT_BOOL( *p == '-' );
218 
219       p++;
220       if ( p == limit )
221         goto Bad;
222 
223       /* only a single sign is allowed */
224       if ( *p == '-' || *p == '+' )
225         return 0;
226     }
227 
228     /* read the integer part */
229     if ( *p != '.' )
230     {
231       curp     = p;
232       integral = PS_Conv_ToInt( &p, limit );
233 
234       if ( p == curp )
235         return 0;
236 
237       if ( integral > 0x7FFF )
238         have_overflow = 1;
239       else
240         integral = (FT_Fixed)( (FT_UInt32)integral << 16 );
241     }
242 
243     /* read the decimal part */
244     if ( p < limit && *p == '.' )
245     {
246       p++;
247 
248       for ( ; p < limit; p++ )
249       {
250         FT_Char  c;
251 
252 
253         if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
254           break;
255 
256         c = ft_char_table[*p & 0x7F];
257 
258         if ( c < 0 || c >= 10 )
259           break;
260 
261         /* only add digit if we don't overflow */
262         if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL )
263         {
264           decimal = decimal * 10 + c;
265 
266           if ( !integral && power_ten > 0 )
267             power_ten--;
268           else
269             divider *= 10;
270         }
271       }
272     }
273 
274     /* read exponent, if any */
275     if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
276     {
277       FT_Long  exponent;
278 
279 
280       p++;
281 
282       curp     = p;
283       exponent = PS_Conv_ToInt( &p, limit );
284 
285       if ( curp == p )
286         return 0;
287 
288       /* arbitrarily limit exponent */
289       if ( exponent > 1000 )
290         have_overflow = 1;
291       else if ( exponent < -1000 )
292         have_underflow = 1;
293       else
294         power_ten += exponent;
295     }
296 
297     *cursor = p;
298 
299     if ( !integral && !decimal )
300       return 0;
301 
302     if ( have_overflow )
303       goto Overflow;
304     if ( have_underflow )
305       goto Underflow;
306 
307     while ( power_ten > 0 )
308     {
309       if ( integral >= 0xCCCCCCCL )
310         goto Overflow;
311       integral *= 10;
312 
313       if ( decimal >= 0xCCCCCCCL )
314       {
315         if ( divider == 1 )
316           goto Overflow;
317         divider /= 10;
318       }
319       else
320         decimal *= 10;
321 
322       power_ten--;
323     }
324 
325     while ( power_ten < 0 )
326     {
327       integral /= 10;
328       if ( divider < 0xCCCCCCCL )
329         divider *= 10;
330       else
331         decimal /= 10;
332 
333       if ( !integral && !decimal )
334         goto Underflow;
335 
336       power_ten++;
337     }
338 
339     if ( decimal )
340     {
341       decimal = FT_DivFix( decimal, divider );
342       /* it's not necessary to check this addition for overflow */
343       /* due to the structure of the real number representation */
344       integral += decimal;
345     }
346 
347   Exit:
348     if ( sign )
349       integral = -integral;
350 
351     return integral;
352 
353   Bad:
354     FT_TRACE4(( "!!!END OF DATA:!!!" ));
355     return 0;
356 
357   Overflow:
358     integral = 0x7FFFFFFFL;
359     FT_TRACE4(( "!!!OVERFLOW:!!!" ));
360     goto Exit;
361 
362   Underflow:
363     FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
364     return 0;
365   }
366 
367 
368 #if 0
369   FT_LOCAL_DEF( FT_UInt )
370   PS_Conv_StringDecode( FT_Byte**  cursor,
371                         FT_Byte*   limit,
372                         FT_Byte*   buffer,
373                         FT_Offset  n )
374   {
375     FT_Byte*  p;
376     FT_UInt   r = 0;
377 
378 
379     for ( p = *cursor; r < n && p < limit; p++ )
380     {
381       FT_Byte  b;
382 
383 
384       if ( *p != '\\' )
385       {
386         buffer[r++] = *p;
387 
388         continue;
389       }
390 
391       p++;
392 
393       switch ( *p )
394       {
395       case 'n':
396         b = '\n';
397         break;
398       case 'r':
399         b = '\r';
400         break;
401       case 't':
402         b = '\t';
403         break;
404       case 'b':
405         b = '\b';
406         break;
407       case 'f':
408         b = '\f';
409         break;
410       case '\r':
411         p++;
412         if ( *p != '\n' )
413         {
414           b = *p;
415 
416           break;
417         }
418         /* no break */
419       case '\n':
420         continue;
421         break;
422       default:
423         if ( IS_PS_DIGIT( *p ) )
424         {
425           b = *p - '0';
426 
427           p++;
428 
429           if ( IS_PS_DIGIT( *p ) )
430           {
431             b = b * 8 + *p - '0';
432 
433             p++;
434 
435             if ( IS_PS_DIGIT( *p ) )
436               b = b * 8 + *p - '0';
437             else
438             {
439               buffer[r++] = b;
440               b = *p;
441             }
442           }
443           else
444           {
445             buffer[r++] = b;
446             b = *p;
447           }
448         }
449         else
450           b = *p;
451         break;
452       }
453 
454       buffer[r++] = b;
455     }
456 
457     *cursor = p;
458 
459     return r;
460   }
461 #endif /* 0 */
462 
463 
464   FT_LOCAL_DEF( FT_UInt )
PS_Conv_ASCIIHexDecode(FT_Byte ** cursor,FT_Byte * limit,FT_Byte * buffer,FT_Offset n)465   PS_Conv_ASCIIHexDecode( FT_Byte**  cursor,
466                           FT_Byte*   limit,
467                           FT_Byte*   buffer,
468                           FT_Offset  n )
469   {
470     FT_Byte*  p;
471     FT_UInt   r   = 0;
472     FT_UInt   w   = 0;
473     FT_UInt   pad = 0x01;
474 
475 
476     n *= 2;
477 
478 #if 1
479 
480     p = *cursor;
481 
482     if ( p >= limit )
483       return 0;
484 
485     if ( n > (FT_UInt)( limit - p ) )
486       n = (FT_UInt)( limit - p );
487 
488     /* we try to process two nibbles at a time to be as fast as possible */
489     for ( ; r < n; r++ )
490     {
491       FT_UInt  c = p[r];
492 
493 
494       if ( IS_PS_SPACE( c ) )
495         continue;
496 
497       if ( c OP 0x80 )
498         break;
499 
500       c = (FT_UInt)ft_char_table[c & 0x7F];
501       if ( c >= 16 )
502         break;
503 
504       pad = ( pad << 4 ) | c;
505       if ( pad & 0x100 )
506       {
507         buffer[w++] = (FT_Byte)pad;
508         pad         = 0x01;
509       }
510     }
511 
512     if ( pad != 0x01 )
513       buffer[w++] = (FT_Byte)( pad << 4 );
514 
515     *cursor = p + r;
516 
517     return w;
518 
519 #else /* 0 */
520 
521     for ( r = 0; r < n; r++ )
522     {
523       FT_Char  c;
524 
525 
526       if ( IS_PS_SPACE( *p ) )
527         continue;
528 
529       if ( *p OP 0x80 )
530         break;
531 
532       c = ft_char_table[*p & 0x7F];
533 
534       if ( (unsigned)c >= 16 )
535         break;
536 
537       if ( r & 1 )
538       {
539         *buffer = (FT_Byte)(*buffer + c);
540         buffer++;
541       }
542       else
543         *buffer = (FT_Byte)(c << 4);
544 
545       r++;
546     }
547 
548     *cursor = p;
549 
550     return ( r + 1 ) / 2;
551 
552 #endif /* 0 */
553 
554   }
555 
556 
557   FT_LOCAL_DEF( FT_UInt )
PS_Conv_EexecDecode(FT_Byte ** cursor,FT_Byte * limit,FT_Byte * buffer,FT_Offset n,FT_UShort * seed)558   PS_Conv_EexecDecode( FT_Byte**   cursor,
559                        FT_Byte*    limit,
560                        FT_Byte*    buffer,
561                        FT_Offset   n,
562                        FT_UShort*  seed )
563   {
564     FT_Byte*  p;
565     FT_UInt   r;
566     FT_UInt   s = *seed;
567 
568 
569 #if 1
570 
571     p = *cursor;
572 
573     if ( p >= limit )
574       return 0;
575 
576     if ( n > (FT_UInt)(limit - p) )
577       n = (FT_UInt)(limit - p);
578 
579     for ( r = 0; r < n; r++ )
580     {
581       FT_UInt  val = p[r];
582       FT_UInt  b   = ( val ^ ( s >> 8 ) );
583 
584 
585       s         = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
586       buffer[r] = (FT_Byte) b;
587     }
588 
589     *cursor = p + n;
590     *seed   = (FT_UShort)s;
591 
592 #else /* 0 */
593 
594     for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
595     {
596       FT_Byte  b = (FT_Byte)( *p ^ ( s >> 8 ) );
597 
598 
599       s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
600       *buffer++ = b;
601     }
602     *cursor = p;
603     *seed   = s;
604 
605 #endif /* 0 */
606 
607     return r;
608   }
609 
610 
611 /* END */
612