/src/freetype/src/base/ftstream.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 864 lines · 617 code · 201 blank · 46 comment · 79 complexity · 94a01dcef63db162faf50fe7715054f7 MD5 · raw file

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