Home | History | Annotate | Download | only in psaux
      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