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