1 /****************************************************************************
   2  *
   3  * psconv.c
   4  *
   5  *   Some convenience conversions (body).
   6  *
   7  * Copyright (C) 2006-2019 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  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       /* 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 )
 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 )
 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 )
 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 )
 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 */