static FT_Error cff_index_init( CFF_Index idx, FT_Stream stream, FT_Bool load ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort count; FT_MEM_ZERO( idx, sizeof ( *idx ) ); idx->stream = stream; idx->start = FT_STREAM_POS(); if ( !FT_READ_USHORT( count ) && count > 0 ) { FT_Byte offsize; FT_ULong size; /* there is at least one element; read the offset size, */ /* then access the offset table to compute the index's total size */ if ( FT_READ_BYTE( offsize ) ) goto Exit; if ( offsize < 1 || offsize > 4 ) { error = FT_Err_Invalid_Table; goto Exit; } idx->count = count; idx->off_size = offsize; size = (FT_ULong)( count + 1 ) * offsize; idx->data_offset = idx->start + 3 + size; if ( FT_STREAM_SKIP( size - offsize ) ) goto Exit; size = cff_index_read_offset( idx, &error ); if ( error ) goto Exit; if ( size == 0 ) { error = CFF_Err_Invalid_Table; goto Exit; } idx->data_size = --size; if ( load ) { /* load the data */ if ( FT_FRAME_EXTRACT( size, idx->bytes ) ) goto Exit; } else { /* skip the data */ if ( FT_STREAM_SKIP( size ) ) goto Exit; } } Exit: if ( error ) FT_FREE( idx->offsets ); return error; }
cff_index_access_element( CFF_Index idx, FT_UInt element, FT_Byte** pbytes, FT_ULong* pbyte_len ) { FT_Error error = CFF_Err_Ok; if ( idx && idx->count > element ) { /* compute start and end offsets */ FT_Stream stream = idx->stream; FT_ULong off1, off2 = 0; /* load offsets from file or the offset table */ if ( !idx->offsets ) { FT_ULong pos = element * idx->off_size; if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) goto Exit; off1 = cff_index_read_offset( idx, &error ); if ( error ) goto Exit; if ( off1 != 0 ) { do { element++; off2 = cff_index_read_offset( idx, &error ); } while ( off2 == 0 && element < idx->count ); } } else /* use offsets table */ { off1 = idx->offsets[element]; if ( off1 ) { do { element++; off2 = idx->offsets[element]; } while ( off2 == 0 && element < idx->count ); } } /* access element */ if ( off1 && off2 > off1 ) { *pbyte_len = off2 - off1; if ( idx->bytes ) { /* this index was completely loaded in memory, that's easy */ *pbytes = idx->bytes + off1 - 1; } else { /* this index is still on disk/file, access it through a frame */ if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) goto Exit; } } else { /* empty index element */ *pbytes = 0; *pbyte_len = 0; } } else error = CFF_Err_Invalid_Argument; Exit: return error; }
cff_index_access_element( CFF_Index idx, FT_UInt element, FT_Byte** pbytes, FT_ULong* pbyte_len ) { FT_Error error = FT_Err_Ok; if ( idx && idx->count > element ) { /* compute start and end offsets */ FT_Stream stream = idx->stream; FT_ULong off1, off2 = 0; /* load offsets from file or the offset table */ if ( !idx->offsets ) { FT_ULong pos = element * idx->off_size; if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) goto Exit; off1 = cff_index_read_offset( idx, &error ); if ( error ) goto Exit; if ( off1 != 0 ) { do { element++; off2 = cff_index_read_offset( idx, &error ); } while ( off2 == 0 && element < idx->count ); } } else /* use offsets table */ { off1 = idx->offsets[element]; if ( off1 ) { do { element++; off2 = idx->offsets[element]; } while ( off2 == 0 && element < idx->count ); } } /* XXX: should check off2 does not exceed the end of this entry; */ /* at present, only truncate off2 at the end of this stream */ if ( off2 > stream->size + 1 || idx->data_offset > stream->size - off2 + 1 ) { FT_ERROR(( "cff_index_access_element:" " offset to next entry (%d)" " exceeds the end of stream (%d)\n", off2, stream->size - idx->data_offset + 1 )); off2 = stream->size - idx->data_offset + 1; } /* access element */ if ( off1 && off2 > off1 ) { *pbyte_len = off2 - off1; if ( idx->bytes ) { /* this index was completely loaded in memory, that's easy */ *pbytes = idx->bytes + off1 - 1; } else { /* this index is still on disk/file, access it through a frame */ if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) goto Exit; } } else { /* empty index element */ *pbytes = 0; *pbyte_len = 0; } } else error = FT_THROW( Invalid_Argument ); Exit: return error; }