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