Home | History | Annotate | Download | only in psaux
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  psconv.c                                                               */
      4 /*                                                                         */
      5 /*    Some convenience conversions (body).                                 */
      6 /*                                                                         */
      7 /*  Copyright 2006-2015 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         /* only add digit if we don't overflow */
    254         if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL )
    255         {
    256           decimal = decimal * 10 + c;
    257 
    258           if ( !integral && power_ten > 0 )
    259             power_ten--;
    260           else
    261             divider *= 10;
    262         }
    263       }
    264     }
    265 
    266     /* read exponent, if any */
    267     if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
    268     {
    269       FT_Long  exponent;
    270 
    271 
    272       p++;
    273 
    274       curp     = p;
    275       exponent = PS_Conv_ToInt( &p, limit );
    276 
    277       if ( curp == p )
    278         return 0;
    279 
    280       /* arbitrarily limit exponent */
    281       if ( exponent > 1000 )
    282         have_overflow = 1;
    283       else if ( exponent < -1000 )
    284         have_underflow = 1;
    285       else
    286         power_ten += exponent;
    287     }
    288 
    289     *cursor = p;
    290 
    291     if ( !integral && !decimal )
    292       return 0;
    293 
    294     if ( have_overflow )
    295       goto Overflow;
    296     if ( have_underflow )
    297       goto Underflow;
    298 
    299     while ( power_ten > 0 )
    300     {
    301       if ( integral >= 0xCCCCCCCL )
    302         goto Overflow;
    303       integral *= 10;
    304 
    305       if ( decimal >= 0xCCCCCCCL )
    306       {
    307         if ( divider == 1 )
    308           goto Overflow;
    309         divider /= 10;
    310       }
    311       else
    312         decimal *= 10;
    313 
    314       power_ten--;
    315     }
    316 
    317     while ( power_ten < 0 )
    318     {
    319       integral /= 10;
    320       if ( divider < 0xCCCCCCCL )
    321         divider *= 10;
    322       else
    323         decimal /= 10;
    324 
    325       if ( !integral && !decimal )
    326         goto Underflow;
    327 
    328       power_ten++;
    329     }
    330 
    331     if ( decimal )
    332     {
    333       decimal = FT_DivFix( decimal, divider );
    334       /* it's not necessary to check this addition for overflow */
    335       /* due to the structure of the real number representation */
    336       integral += decimal;
    337     }
    338 
    339   Exit:
    340     if ( sign )
    341       integral = -integral;
    342 
    343     return integral;
    344 
    345   Bad:
    346     FT_TRACE4(( "!!!END OF DATA:!!!" ));
    347     return 0;
    348 
    349   Overflow:
    350     integral = 0x7FFFFFFFL;
    351     FT_TRACE4(( "!!!OVERFLOW:!!!" ));
    352     goto Exit;
    353 
    354   Underflow:
    355     FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
    356     return 0;
    357   }
    358 
    359 
    360 #if 0
    361   FT_LOCAL_DEF( FT_UInt )
    362   PS_Conv_StringDecode( FT_Byte**  cursor,
    363                         FT_Byte*   limit,
    364                         FT_Byte*   buffer,
    365                         FT_Offset  n )
    366   {
    367     FT_Byte*  p;
    368     FT_UInt   r = 0;
    369 
    370 
    371     for ( p = *cursor; r < n && p < limit; p++ )
    372     {
    373       FT_Byte  b;
    374 
    375 
    376       if ( *p != '\\' )
    377       {
    378         buffer[r++] = *p;
    379 
    380         continue;
    381       }
    382 
    383       p++;
    384 
    385       switch ( *p )
    386       {
    387       case 'n':
    388         b = '\n';
    389         break;
    390       case 'r':
    391         b = '\r';
    392         break;
    393       case 't':
    394         b = '\t';
    395         break;
    396       case 'b':
    397         b = '\b';
    398         break;
    399       case 'f':
    400         b = '\f';
    401         break;
    402       case '\r':
    403         p++;
    404         if ( *p != '\n' )
    405         {
    406           b = *p;
    407 
    408           break;
    409         }
    410         /* no break */
    411       case '\n':
    412         continue;
    413         break;
    414       default:
    415         if ( IS_PS_DIGIT( *p ) )
    416         {
    417           b = *p - '0';
    418 
    419           p++;
    420 
    421           if ( IS_PS_DIGIT( *p ) )
    422           {
    423             b = b * 8 + *p - '0';
    424 
    425             p++;
    426 
    427             if ( IS_PS_DIGIT( *p ) )
    428               b = b * 8 + *p - '0';
    429             else
    430             {
    431               buffer[r++] = b;
    432               b = *p;
    433             }
    434           }
    435           else
    436           {
    437             buffer[r++] = b;
    438             b = *p;
    439           }
    440         }
    441         else
    442           b = *p;
    443         break;
    444       }
    445 
    446       buffer[r++] = b;
    447     }
    448 
    449     *cursor = p;
    450 
    451     return r;
    452   }
    453 #endif /* 0 */
    454 
    455 
    456   FT_LOCAL_DEF( FT_UInt )
    457   PS_Conv_ASCIIHexDecode( FT_Byte**  cursor,
    458                           FT_Byte*   limit,
    459                           FT_Byte*   buffer,
    460                           FT_Offset  n )
    461   {
    462     FT_Byte*  p;
    463     FT_UInt   r   = 0;
    464     FT_UInt   w   = 0;
    465     FT_UInt   pad = 0x01;
    466 
    467 
    468     n *= 2;
    469 
    470 #if 1
    471 
    472     p = *cursor;
    473 
    474     if ( p >= limit )
    475       return 0;
    476 
    477     if ( n > (FT_UInt)( limit - p ) )
    478       n = (FT_UInt)( limit - p );
    479 
    480     /* we try to process two nibbles at a time to be as fast as possible */
    481     for ( ; r < n; r++ )
    482     {
    483       FT_UInt  c = p[r];
    484 
    485 
    486       if ( IS_PS_SPACE( c ) )
    487         continue;
    488 
    489       if ( c OP 0x80 )
    490         break;
    491 
    492       c = (FT_UInt)ft_char_table[c & 0x7F];
    493       if ( c >= 16 )
    494         break;
    495 
    496       pad = ( pad << 4 ) | c;
    497       if ( pad & 0x100 )
    498       {
    499         buffer[w++] = (FT_Byte)pad;
    500         pad         = 0x01;
    501       }
    502     }
    503 
    504     if ( pad != 0x01 )
    505       buffer[w++] = (FT_Byte)( pad << 4 );
    506 
    507     *cursor = p + r;
    508 
    509     return w;
    510 
    511 #else /* 0 */
    512 
    513     for ( r = 0; r < n; r++ )
    514     {
    515       FT_Char  c;
    516 
    517 
    518       if ( IS_PS_SPACE( *p ) )
    519         continue;
    520 
    521       if ( *p OP 0x80 )
    522         break;
    523 
    524       c = ft_char_table[*p & 0x7F];
    525 
    526       if ( (unsigned)c >= 16 )
    527         break;
    528 
    529       if ( r & 1 )
    530       {
    531         *buffer = (FT_Byte)(*buffer + c);
    532         buffer++;
    533       }
    534       else
    535         *buffer = (FT_Byte)(c << 4);
    536 
    537       r++;
    538     }
    539 
    540     *cursor = p;
    541 
    542     return ( r + 1 ) / 2;
    543 
    544 #endif /* 0 */
    545 
    546   }
    547 
    548 
    549   FT_LOCAL_DEF( FT_UInt )
    550   PS_Conv_EexecDecode( FT_Byte**   cursor,
    551                        FT_Byte*    limit,
    552                        FT_Byte*    buffer,
    553                        FT_Offset   n,
    554                        FT_UShort*  seed )
    555   {
    556     FT_Byte*  p;
    557     FT_UInt   r;
    558     FT_UInt   s = *seed;
    559 
    560 
    561 #if 1
    562 
    563     p = *cursor;
    564 
    565     if ( p >= limit )
    566       return 0;
    567 
    568     if ( n > (FT_UInt)(limit - p) )
    569       n = (FT_UInt)(limit - p);
    570 
    571     for ( r = 0; r < n; r++ )
    572     {
    573       FT_UInt  val = p[r];
    574       FT_UInt  b   = ( val ^ ( s >> 8 ) );
    575 
    576 
    577       s         = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
    578       buffer[r] = (FT_Byte) b;
    579     }
    580 
    581     *cursor = p + n;
    582     *seed   = (FT_UShort)s;
    583 
    584 #else /* 0 */
    585 
    586     for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
    587     {
    588       FT_Byte  b = (FT_Byte)( *p ^ ( s >> 8 ) );
    589 
    590 
    591       s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
    592       *buffer++ = b;
    593     }
    594     *cursor = p;
    595     *seed   = s;
    596 
    597 #endif /* 0 */
    598 
    599     return r;
    600   }
    601 
    602 
    603 /* END */
    604