1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* ftstream.c */ |
|
4 /* */ |
|
5 /* I/O stream support (body). */ |
|
6 /* */ |
|
7 /* Copyright 2000-2002, 2004-2006, 2008-2011 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_STREAM_H |
|
21 #include FT_INTERNAL_DEBUG_H |
|
22 |
|
23 |
|
24 /*************************************************************************/ |
|
25 /* */ |
|
26 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
27 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
28 /* messages during execution. */ |
|
29 /* */ |
|
30 #undef FT_COMPONENT |
|
31 #define FT_COMPONENT trace_stream |
|
32 |
|
33 |
|
34 FT_BASE_DEF( void ) |
|
35 FT_Stream_OpenMemory( FT_Stream stream, |
|
36 const FT_Byte* base, |
|
37 FT_ULong size ) |
|
38 { |
|
39 stream->base = (FT_Byte*) base; |
|
40 stream->size = size; |
|
41 stream->pos = 0; |
|
42 stream->cursor = 0; |
|
43 stream->read = 0; |
|
44 stream->close = 0; |
|
45 } |
|
46 |
|
47 |
|
48 FT_BASE_DEF( void ) |
|
49 FT_Stream_Close( FT_Stream stream ) |
|
50 { |
|
51 if ( stream && stream->close ) |
|
52 stream->close( stream ); |
|
53 } |
|
54 |
|
55 |
|
56 FT_BASE_DEF( FT_Error ) |
|
57 FT_Stream_Seek( FT_Stream stream, |
|
58 FT_ULong pos ) |
|
59 { |
|
60 FT_Error error = FT_Err_Ok; |
|
61 |
|
62 |
|
63 if ( stream->read ) |
|
64 { |
|
65 if ( stream->read( stream, pos, 0, 0 ) ) |
|
66 { |
|
67 FT_ERROR(( "FT_Stream_Seek:" |
|
68 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
69 pos, stream->size )); |
|
70 |
|
71 error = FT_Err_Invalid_Stream_Operation; |
|
72 } |
|
73 } |
|
74 /* note that seeking to the first position after the file is valid */ |
|
75 else if ( pos > stream->size ) |
|
76 { |
|
77 FT_ERROR(( "FT_Stream_Seek:" |
|
78 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
79 pos, stream->size )); |
|
80 |
|
81 error = FT_Err_Invalid_Stream_Operation; |
|
82 } |
|
83 |
|
84 if ( !error ) |
|
85 stream->pos = pos; |
|
86 |
|
87 return error; |
|
88 } |
|
89 |
|
90 |
|
91 FT_BASE_DEF( FT_Error ) |
|
92 FT_Stream_Skip( FT_Stream stream, |
|
93 FT_Long distance ) |
|
94 { |
|
95 if ( distance < 0 ) |
|
96 return FT_Err_Invalid_Stream_Operation; |
|
97 |
|
98 return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) ); |
|
99 } |
|
100 |
|
101 |
|
102 FT_BASE_DEF( FT_Long ) |
|
103 FT_Stream_Pos( FT_Stream stream ) |
|
104 { |
|
105 return stream->pos; |
|
106 } |
|
107 |
|
108 |
|
109 FT_BASE_DEF( FT_Error ) |
|
110 FT_Stream_Read( FT_Stream stream, |
|
111 FT_Byte* buffer, |
|
112 FT_ULong count ) |
|
113 { |
|
114 return FT_Stream_ReadAt( stream, stream->pos, buffer, count ); |
|
115 } |
|
116 |
|
117 |
|
118 FT_BASE_DEF( FT_Error ) |
|
119 FT_Stream_ReadAt( FT_Stream stream, |
|
120 FT_ULong pos, |
|
121 FT_Byte* buffer, |
|
122 FT_ULong count ) |
|
123 { |
|
124 FT_Error error = FT_Err_Ok; |
|
125 FT_ULong read_bytes; |
|
126 |
|
127 |
|
128 if ( pos >= stream->size ) |
|
129 { |
|
130 FT_ERROR(( "FT_Stream_ReadAt:" |
|
131 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
132 pos, stream->size )); |
|
133 |
|
134 return FT_Err_Invalid_Stream_Operation; |
|
135 } |
|
136 |
|
137 if ( stream->read ) |
|
138 read_bytes = stream->read( stream, pos, buffer, count ); |
|
139 else |
|
140 { |
|
141 read_bytes = stream->size - pos; |
|
142 if ( read_bytes > count ) |
|
143 read_bytes = count; |
|
144 |
|
145 FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); |
|
146 } |
|
147 |
|
148 stream->pos = pos + read_bytes; |
|
149 |
|
150 if ( read_bytes < count ) |
|
151 { |
|
152 FT_ERROR(( "FT_Stream_ReadAt:" |
|
153 " invalid read; expected %lu bytes, got %lu\n", |
|
154 count, read_bytes )); |
|
155 |
|
156 error = FT_Err_Invalid_Stream_Operation; |
|
157 } |
|
158 |
|
159 return error; |
|
160 } |
|
161 |
|
162 |
|
163 FT_BASE_DEF( FT_ULong ) |
|
164 FT_Stream_TryRead( FT_Stream stream, |
|
165 FT_Byte* buffer, |
|
166 FT_ULong count ) |
|
167 { |
|
168 FT_ULong read_bytes = 0; |
|
169 |
|
170 |
|
171 if ( stream->pos >= stream->size ) |
|
172 goto Exit; |
|
173 |
|
174 if ( stream->read ) |
|
175 read_bytes = stream->read( stream, stream->pos, buffer, count ); |
|
176 else |
|
177 { |
|
178 read_bytes = stream->size - stream->pos; |
|
179 if ( read_bytes > count ) |
|
180 read_bytes = count; |
|
181 |
|
182 FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes ); |
|
183 } |
|
184 |
|
185 stream->pos += read_bytes; |
|
186 |
|
187 Exit: |
|
188 return read_bytes; |
|
189 } |
|
190 |
|
191 |
|
192 FT_BASE_DEF( FT_Error ) |
|
193 FT_Stream_ExtractFrame( FT_Stream stream, |
|
194 FT_ULong count, |
|
195 FT_Byte** pbytes ) |
|
196 { |
|
197 FT_Error error; |
|
198 |
|
199 |
|
200 error = FT_Stream_EnterFrame( stream, count ); |
|
201 if ( !error ) |
|
202 { |
|
203 *pbytes = (FT_Byte*)stream->cursor; |
|
204 |
|
205 /* equivalent to FT_Stream_ExitFrame(), with no memory block release */ |
|
206 stream->cursor = 0; |
|
207 stream->limit = 0; |
|
208 } |
|
209 |
|
210 return error; |
|
211 } |
|
212 |
|
213 |
|
214 FT_BASE_DEF( void ) |
|
215 FT_Stream_ReleaseFrame( FT_Stream stream, |
|
216 FT_Byte** pbytes ) |
|
217 { |
|
218 if ( stream && stream->read ) |
|
219 { |
|
220 FT_Memory memory = stream->memory; |
|
221 |
|
222 #ifdef FT_DEBUG_MEMORY |
|
223 ft_mem_free( memory, *pbytes ); |
|
224 *pbytes = NULL; |
|
225 #else |
|
226 FT_FREE( *pbytes ); |
|
227 #endif |
|
228 } |
|
229 *pbytes = 0; |
|
230 } |
|
231 |
|
232 |
|
233 FT_BASE_DEF( FT_Error ) |
|
234 FT_Stream_EnterFrame( FT_Stream stream, |
|
235 FT_ULong count ) |
|
236 { |
|
237 FT_Error error = FT_Err_Ok; |
|
238 FT_ULong read_bytes; |
|
239 |
|
240 |
|
241 /* check for nested frame access */ |
|
242 FT_ASSERT( stream && stream->cursor == 0 ); |
|
243 |
|
244 if ( stream->read ) |
|
245 { |
|
246 /* allocate the frame in memory */ |
|
247 FT_Memory memory = stream->memory; |
|
248 |
|
249 |
|
250 /* simple sanity check */ |
|
251 if ( count > stream->size ) |
|
252 { |
|
253 FT_ERROR(( "FT_Stream_EnterFrame:" |
|
254 " frame size (%lu) larger than stream size (%lu)\n", |
|
255 count, stream->size )); |
|
256 |
|
257 error = FT_Err_Invalid_Stream_Operation; |
|
258 goto Exit; |
|
259 } |
|
260 |
|
261 #ifdef FT_DEBUG_MEMORY |
|
262 /* assume _ft_debug_file and _ft_debug_lineno are already set */ |
|
263 stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error ); |
|
264 if ( error ) |
|
265 goto Exit; |
|
266 #else |
|
267 if ( FT_QALLOC( stream->base, count ) ) |
|
268 goto Exit; |
|
269 #endif |
|
270 /* read it */ |
|
271 read_bytes = stream->read( stream, stream->pos, |
|
272 stream->base, count ); |
|
273 if ( read_bytes < count ) |
|
274 { |
|
275 FT_ERROR(( "FT_Stream_EnterFrame:" |
|
276 " invalid read; expected %lu bytes, got %lu\n", |
|
277 count, read_bytes )); |
|
278 |
|
279 FT_FREE( stream->base ); |
|
280 error = FT_Err_Invalid_Stream_Operation; |
|
281 } |
|
282 stream->cursor = stream->base; |
|
283 stream->limit = stream->cursor + count; |
|
284 stream->pos += read_bytes; |
|
285 } |
|
286 else |
|
287 { |
|
288 /* check current and new position */ |
|
289 if ( stream->pos >= stream->size || |
|
290 stream->size - stream->pos < count ) |
|
291 { |
|
292 FT_ERROR(( "FT_Stream_EnterFrame:" |
|
293 " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n", |
|
294 stream->pos, count, stream->size )); |
|
295 |
|
296 error = FT_Err_Invalid_Stream_Operation; |
|
297 goto Exit; |
|
298 } |
|
299 |
|
300 /* set cursor */ |
|
301 stream->cursor = stream->base + stream->pos; |
|
302 stream->limit = stream->cursor + count; |
|
303 stream->pos += count; |
|
304 } |
|
305 |
|
306 Exit: |
|
307 return error; |
|
308 } |
|
309 |
|
310 |
|
311 FT_BASE_DEF( void ) |
|
312 FT_Stream_ExitFrame( FT_Stream stream ) |
|
313 { |
|
314 /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */ |
|
315 /* that it is possible to access a frame of length 0 in */ |
|
316 /* some weird fonts (usually, when accessing an array of */ |
|
317 /* 0 records, like in some strange kern tables). */ |
|
318 /* */ |
|
319 /* In this case, the loader code handles the 0-length table */ |
|
320 /* gracefully; however, stream.cursor is really set to 0 by the */ |
|
321 /* FT_Stream_EnterFrame() call, and this is not an error. */ |
|
322 /* */ |
|
323 FT_ASSERT( stream ); |
|
324 |
|
325 if ( stream->read ) |
|
326 { |
|
327 FT_Memory memory = stream->memory; |
|
328 |
|
329 #ifdef FT_DEBUG_MEMORY |
|
330 ft_mem_free( memory, stream->base ); |
|
331 stream->base = NULL; |
|
332 #else |
|
333 FT_FREE( stream->base ); |
|
334 #endif |
|
335 } |
|
336 stream->cursor = 0; |
|
337 stream->limit = 0; |
|
338 } |
|
339 |
|
340 |
|
341 FT_BASE_DEF( FT_Char ) |
|
342 FT_Stream_GetChar( FT_Stream stream ) |
|
343 { |
|
344 FT_Char result; |
|
345 |
|
346 |
|
347 FT_ASSERT( stream && stream->cursor ); |
|
348 |
|
349 result = 0; |
|
350 if ( stream->cursor < stream->limit ) |
|
351 result = *stream->cursor++; |
|
352 |
|
353 return result; |
|
354 } |
|
355 |
|
356 |
|
357 FT_BASE_DEF( FT_UShort ) |
|
358 FT_Stream_GetUShort( FT_Stream stream ) |
|
359 { |
|
360 FT_Byte* p; |
|
361 FT_Short result; |
|
362 |
|
363 |
|
364 FT_ASSERT( stream && stream->cursor ); |
|
365 |
|
366 result = 0; |
|
367 p = stream->cursor; |
|
368 if ( p + 1 < stream->limit ) |
|
369 result = FT_NEXT_USHORT( p ); |
|
370 stream->cursor = p; |
|
371 |
|
372 return result; |
|
373 } |
|
374 |
|
375 |
|
376 FT_BASE_DEF( FT_UShort ) |
|
377 FT_Stream_GetUShortLE( FT_Stream stream ) |
|
378 { |
|
379 FT_Byte* p; |
|
380 FT_Short result; |
|
381 |
|
382 |
|
383 FT_ASSERT( stream && stream->cursor ); |
|
384 |
|
385 result = 0; |
|
386 p = stream->cursor; |
|
387 if ( p + 1 < stream->limit ) |
|
388 result = FT_NEXT_USHORT_LE( p ); |
|
389 stream->cursor = p; |
|
390 |
|
391 return result; |
|
392 } |
|
393 |
|
394 |
|
395 FT_BASE_DEF( FT_ULong ) |
|
396 FT_Stream_GetUOffset( FT_Stream stream ) |
|
397 { |
|
398 FT_Byte* p; |
|
399 FT_Long result; |
|
400 |
|
401 |
|
402 FT_ASSERT( stream && stream->cursor ); |
|
403 |
|
404 result = 0; |
|
405 p = stream->cursor; |
|
406 if ( p + 2 < stream->limit ) |
|
407 result = FT_NEXT_UOFF3( p ); |
|
408 stream->cursor = p; |
|
409 return result; |
|
410 } |
|
411 |
|
412 |
|
413 FT_BASE_DEF( FT_ULong ) |
|
414 FT_Stream_GetULong( FT_Stream stream ) |
|
415 { |
|
416 FT_Byte* p; |
|
417 FT_Long result; |
|
418 |
|
419 |
|
420 FT_ASSERT( stream && stream->cursor ); |
|
421 |
|
422 result = 0; |
|
423 p = stream->cursor; |
|
424 if ( p + 3 < stream->limit ) |
|
425 result = FT_NEXT_ULONG( p ); |
|
426 stream->cursor = p; |
|
427 return result; |
|
428 } |
|
429 |
|
430 |
|
431 FT_BASE_DEF( FT_ULong ) |
|
432 FT_Stream_GetULongLE( FT_Stream stream ) |
|
433 { |
|
434 FT_Byte* p; |
|
435 FT_Long result; |
|
436 |
|
437 |
|
438 FT_ASSERT( stream && stream->cursor ); |
|
439 |
|
440 result = 0; |
|
441 p = stream->cursor; |
|
442 if ( p + 3 < stream->limit ) |
|
443 result = FT_NEXT_ULONG_LE( p ); |
|
444 stream->cursor = p; |
|
445 return result; |
|
446 } |
|
447 |
|
448 |
|
449 FT_BASE_DEF( FT_Char ) |
|
450 FT_Stream_ReadChar( FT_Stream stream, |
|
451 FT_Error* error ) |
|
452 { |
|
453 FT_Byte result = 0; |
|
454 |
|
455 |
|
456 FT_ASSERT( stream ); |
|
457 |
|
458 *error = FT_Err_Ok; |
|
459 |
|
460 if ( stream->read ) |
|
461 { |
|
462 if ( stream->read( stream, stream->pos, &result, 1L ) != 1L ) |
|
463 goto Fail; |
|
464 } |
|
465 else |
|
466 { |
|
467 if ( stream->pos < stream->size ) |
|
468 result = stream->base[stream->pos]; |
|
469 else |
|
470 goto Fail; |
|
471 } |
|
472 stream->pos++; |
|
473 |
|
474 return result; |
|
475 |
|
476 Fail: |
|
477 *error = FT_Err_Invalid_Stream_Operation; |
|
478 FT_ERROR(( "FT_Stream_ReadChar:" |
|
479 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
480 stream->pos, stream->size )); |
|
481 |
|
482 return 0; |
|
483 } |
|
484 |
|
485 |
|
486 FT_BASE_DEF( FT_UShort ) |
|
487 FT_Stream_ReadUShort( FT_Stream stream, |
|
488 FT_Error* error ) |
|
489 { |
|
490 FT_Byte reads[2]; |
|
491 FT_Byte* p = 0; |
|
492 FT_Short result = 0; |
|
493 |
|
494 |
|
495 FT_ASSERT( stream ); |
|
496 |
|
497 *error = FT_Err_Ok; |
|
498 |
|
499 if ( stream->pos + 1 < stream->size ) |
|
500 { |
|
501 if ( stream->read ) |
|
502 { |
|
503 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) |
|
504 goto Fail; |
|
505 |
|
506 p = reads; |
|
507 } |
|
508 else |
|
509 { |
|
510 p = stream->base + stream->pos; |
|
511 } |
|
512 |
|
513 if ( p ) |
|
514 result = FT_NEXT_USHORT( p ); |
|
515 } |
|
516 else |
|
517 goto Fail; |
|
518 |
|
519 stream->pos += 2; |
|
520 |
|
521 return result; |
|
522 |
|
523 Fail: |
|
524 *error = FT_Err_Invalid_Stream_Operation; |
|
525 FT_ERROR(( "FT_Stream_ReadUShort:" |
|
526 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
527 stream->pos, stream->size )); |
|
528 |
|
529 return 0; |
|
530 } |
|
531 |
|
532 |
|
533 FT_BASE_DEF( FT_UShort ) |
|
534 FT_Stream_ReadUShortLE( FT_Stream stream, |
|
535 FT_Error* error ) |
|
536 { |
|
537 FT_Byte reads[2]; |
|
538 FT_Byte* p = 0; |
|
539 FT_Short result = 0; |
|
540 |
|
541 |
|
542 FT_ASSERT( stream ); |
|
543 |
|
544 *error = FT_Err_Ok; |
|
545 |
|
546 if ( stream->pos + 1 < stream->size ) |
|
547 { |
|
548 if ( stream->read ) |
|
549 { |
|
550 if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) |
|
551 goto Fail; |
|
552 |
|
553 p = reads; |
|
554 } |
|
555 else |
|
556 { |
|
557 p = stream->base + stream->pos; |
|
558 } |
|
559 |
|
560 if ( p ) |
|
561 result = FT_NEXT_USHORT_LE( p ); |
|
562 } |
|
563 else |
|
564 goto Fail; |
|
565 |
|
566 stream->pos += 2; |
|
567 |
|
568 return result; |
|
569 |
|
570 Fail: |
|
571 *error = FT_Err_Invalid_Stream_Operation; |
|
572 FT_ERROR(( "FT_Stream_ReadUShortLE:" |
|
573 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
574 stream->pos, stream->size )); |
|
575 |
|
576 return 0; |
|
577 } |
|
578 |
|
579 |
|
580 FT_BASE_DEF( FT_ULong ) |
|
581 FT_Stream_ReadUOffset( FT_Stream stream, |
|
582 FT_Error* error ) |
|
583 { |
|
584 FT_Byte reads[3]; |
|
585 FT_Byte* p = 0; |
|
586 FT_Long result = 0; |
|
587 |
|
588 |
|
589 FT_ASSERT( stream ); |
|
590 |
|
591 *error = FT_Err_Ok; |
|
592 |
|
593 if ( stream->pos + 2 < stream->size ) |
|
594 { |
|
595 if ( stream->read ) |
|
596 { |
|
597 if (stream->read( stream, stream->pos, reads, 3L ) != 3L ) |
|
598 goto Fail; |
|
599 |
|
600 p = reads; |
|
601 } |
|
602 else |
|
603 { |
|
604 p = stream->base + stream->pos; |
|
605 } |
|
606 |
|
607 if ( p ) |
|
608 result = FT_NEXT_UOFF3( p ); |
|
609 } |
|
610 else |
|
611 goto Fail; |
|
612 |
|
613 stream->pos += 3; |
|
614 |
|
615 return result; |
|
616 |
|
617 Fail: |
|
618 *error = FT_Err_Invalid_Stream_Operation; |
|
619 FT_ERROR(( "FT_Stream_ReadUOffset:" |
|
620 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
621 stream->pos, stream->size )); |
|
622 |
|
623 return 0; |
|
624 } |
|
625 |
|
626 |
|
627 FT_BASE_DEF( FT_ULong ) |
|
628 FT_Stream_ReadULong( FT_Stream stream, |
|
629 FT_Error* error ) |
|
630 { |
|
631 FT_Byte reads[4]; |
|
632 FT_Byte* p = 0; |
|
633 FT_Long result = 0; |
|
634 |
|
635 |
|
636 FT_ASSERT( stream ); |
|
637 |
|
638 *error = FT_Err_Ok; |
|
639 |
|
640 if ( stream->pos + 3 < stream->size ) |
|
641 { |
|
642 if ( stream->read ) |
|
643 { |
|
644 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) |
|
645 goto Fail; |
|
646 |
|
647 p = reads; |
|
648 } |
|
649 else |
|
650 { |
|
651 p = stream->base + stream->pos; |
|
652 } |
|
653 |
|
654 if ( p ) |
|
655 result = FT_NEXT_ULONG( p ); |
|
656 } |
|
657 else |
|
658 goto Fail; |
|
659 |
|
660 stream->pos += 4; |
|
661 |
|
662 return result; |
|
663 |
|
664 Fail: |
|
665 *error = FT_Err_Invalid_Stream_Operation; |
|
666 FT_ERROR(( "FT_Stream_ReadULong:" |
|
667 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
668 stream->pos, stream->size )); |
|
669 |
|
670 return 0; |
|
671 } |
|
672 |
|
673 |
|
674 FT_BASE_DEF( FT_ULong ) |
|
675 FT_Stream_ReadULongLE( FT_Stream stream, |
|
676 FT_Error* error ) |
|
677 { |
|
678 FT_Byte reads[4]; |
|
679 FT_Byte* p = 0; |
|
680 FT_Long result = 0; |
|
681 |
|
682 |
|
683 FT_ASSERT( stream ); |
|
684 |
|
685 *error = FT_Err_Ok; |
|
686 |
|
687 if ( stream->pos + 3 < stream->size ) |
|
688 { |
|
689 if ( stream->read ) |
|
690 { |
|
691 if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) |
|
692 goto Fail; |
|
693 |
|
694 p = reads; |
|
695 } |
|
696 else |
|
697 { |
|
698 p = stream->base + stream->pos; |
|
699 } |
|
700 |
|
701 if ( p ) |
|
702 result = FT_NEXT_ULONG_LE( p ); |
|
703 } |
|
704 else |
|
705 goto Fail; |
|
706 |
|
707 stream->pos += 4; |
|
708 |
|
709 return result; |
|
710 |
|
711 Fail: |
|
712 *error = FT_Err_Invalid_Stream_Operation; |
|
713 FT_ERROR(( "FT_Stream_ReadULongLE:" |
|
714 " invalid i/o; pos = 0x%lx, size = 0x%lx\n", |
|
715 stream->pos, stream->size )); |
|
716 |
|
717 return 0; |
|
718 } |
|
719 |
|
720 |
|
721 FT_BASE_DEF( FT_Error ) |
|
722 FT_Stream_ReadFields( FT_Stream stream, |
|
723 const FT_Frame_Field* fields, |
|
724 void* structure ) |
|
725 { |
|
726 FT_Error error; |
|
727 FT_Bool frame_accessed = 0; |
|
728 FT_Byte* cursor; |
|
729 |
|
730 if ( !fields || !stream ) |
|
731 return FT_Err_Invalid_Argument; |
|
732 |
|
733 cursor = stream->cursor; |
|
734 |
|
735 error = FT_Err_Ok; |
|
736 do |
|
737 { |
|
738 FT_ULong value; |
|
739 FT_Int sign_shift; |
|
740 FT_Byte* p; |
|
741 |
|
742 |
|
743 switch ( fields->value ) |
|
744 { |
|
745 case ft_frame_start: /* access a new frame */ |
|
746 error = FT_Stream_EnterFrame( stream, fields->offset ); |
|
747 if ( error ) |
|
748 goto Exit; |
|
749 |
|
750 frame_accessed = 1; |
|
751 cursor = stream->cursor; |
|
752 fields++; |
|
753 continue; /* loop! */ |
|
754 |
|
755 case ft_frame_bytes: /* read a byte sequence */ |
|
756 case ft_frame_skip: /* skip some bytes */ |
|
757 { |
|
758 FT_UInt len = fields->size; |
|
759 |
|
760 |
|
761 if ( cursor + len > stream->limit ) |
|
762 { |
|
763 error = FT_Err_Invalid_Stream_Operation; |
|
764 goto Exit; |
|
765 } |
|
766 |
|
767 if ( fields->value == ft_frame_bytes ) |
|
768 { |
|
769 p = (FT_Byte*)structure + fields->offset; |
|
770 FT_MEM_COPY( p, cursor, len ); |
|
771 } |
|
772 cursor += len; |
|
773 fields++; |
|
774 continue; |
|
775 } |
|
776 |
|
777 case ft_frame_byte: |
|
778 case ft_frame_schar: /* read a single byte */ |
|
779 value = FT_NEXT_BYTE(cursor); |
|
780 sign_shift = 24; |
|
781 break; |
|
782 |
|
783 case ft_frame_short_be: |
|
784 case ft_frame_ushort_be: /* read a 2-byte big-endian short */ |
|
785 value = FT_NEXT_USHORT(cursor); |
|
786 sign_shift = 16; |
|
787 break; |
|
788 |
|
789 case ft_frame_short_le: |
|
790 case ft_frame_ushort_le: /* read a 2-byte little-endian short */ |
|
791 value = FT_NEXT_USHORT_LE(cursor); |
|
792 sign_shift = 16; |
|
793 break; |
|
794 |
|
795 case ft_frame_long_be: |
|
796 case ft_frame_ulong_be: /* read a 4-byte big-endian long */ |
|
797 value = FT_NEXT_ULONG(cursor); |
|
798 sign_shift = 0; |
|
799 break; |
|
800 |
|
801 case ft_frame_long_le: |
|
802 case ft_frame_ulong_le: /* read a 4-byte little-endian long */ |
|
803 value = FT_NEXT_ULONG_LE(cursor); |
|
804 sign_shift = 0; |
|
805 break; |
|
806 |
|
807 case ft_frame_off3_be: |
|
808 case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ |
|
809 value = FT_NEXT_UOFF3(cursor); |
|
810 sign_shift = 8; |
|
811 break; |
|
812 |
|
813 case ft_frame_off3_le: |
|
814 case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ |
|
815 value = FT_NEXT_UOFF3_LE(cursor); |
|
816 sign_shift = 8; |
|
817 break; |
|
818 |
|
819 default: |
|
820 /* otherwise, exit the loop */ |
|
821 stream->cursor = cursor; |
|
822 goto Exit; |
|
823 } |
|
824 |
|
825 /* now, compute the signed value is necessary */ |
|
826 if ( fields->value & FT_FRAME_OP_SIGNED ) |
|
827 value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift ); |
|
828 |
|
829 /* finally, store the value in the object */ |
|
830 |
|
831 p = (FT_Byte*)structure + fields->offset; |
|
832 switch ( fields->size ) |
|
833 { |
|
834 case (8 / FT_CHAR_BIT): |
|
835 *(FT_Byte*)p = (FT_Byte)value; |
|
836 break; |
|
837 |
|
838 case (16 / FT_CHAR_BIT): |
|
839 *(FT_UShort*)p = (FT_UShort)value; |
|
840 break; |
|
841 |
|
842 case (32 / FT_CHAR_BIT): |
|
843 *(FT_UInt32*)p = (FT_UInt32)value; |
|
844 break; |
|
845 |
|
846 default: /* for 64-bit systems */ |
|
847 *(FT_ULong*)p = (FT_ULong)value; |
|
848 } |
|
849 |
|
850 /* go to next field */ |
|
851 fields++; |
|
852 } |
|
853 while ( 1 ); |
|
854 |
|
855 Exit: |
|
856 /* close the frame if it was opened by this read */ |
|
857 if ( frame_accessed ) |
|
858 FT_Stream_ExitFrame( stream ); |
|
859 |
|
860 return error; |
|
861 } |
|
862 |
|
863 |
|
864 /* END */ |
|