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