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 */
612