| /***************************************************************************/ |
| /* */ |
| /* otlcommn.c */ |
| /* */ |
| /* OpenType layout support, common tables (body). */ |
| /* */ |
| /* Copyright 2002 by */ |
| /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
| /* */ |
| /* This file is part of the FreeType project, and may only be used, */ |
| /* modified, and distributed under the terms of the FreeType project */ |
| /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
| /* this file you indicate that you have read the license and */ |
| /* understand and accept it fully. */ |
| /* */ |
| /***************************************************************************/ |
| |
| |
| #include "otlayout.h" |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** COVERAGE TABLE *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_coverage_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p; |
| OTL_UInt format; |
| |
| |
| if ( table + 4 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| format = OTL_NEXT_USHORT( p ); |
| switch ( format ) |
| { |
| case 1: |
| { |
| OTL_UInt count = OTL_NEXT_USHORT( p ); |
| |
| |
| if ( p + count * 2 >= valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| /* XXX: check glyph indices */ |
| } |
| break; |
| |
| case 2: |
| { |
| OTL_UInt n, num_ranges = OTL_NEXT_USHORT( p ); |
| OTL_UInt start, end, start_cover, total = 0, last = 0; |
| |
| |
| if ( p + num_ranges * 6 >= valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| for ( n = 0; n < num_ranges; n++ ) |
| { |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| start_cover = OTL_NEXT_USHORT( p ); |
| |
| if ( start > end || start_cover != total ) |
| OTL_INVALID_DATA; |
| |
| if ( n > 0 && start <= last ) |
| OTL_INVALID_DATA; |
| |
| total += end - start + 1; |
| last = end; |
| } |
| } |
| break; |
| |
| default: |
| OTL_INVALID_FORMAT; |
| } |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_coverage_get_count( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt format = OTL_NEXT_USHORT( p ); |
| OTL_UInt count = OTL_NEXT_USHORT( p ); |
| OTL_UInt result = 0; |
| |
| |
| switch ( format ) |
| { |
| case 1: |
| return count; |
| |
| case 2: |
| { |
| OTL_UInt start, end; |
| |
| |
| for ( ; count > 0; count-- ) |
| { |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| p += 2; /* skip start_index */ |
| |
| result += end - start + 1; |
| } |
| } |
| break; |
| |
| default: |
| ; |
| } |
| |
| return result; |
| } |
| |
| |
| OTL_LOCALDEF( OTL_Int ) |
| otl_coverage_get_index( OTL_Bytes table, |
| OTL_UInt glyph_index ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt format = OTL_NEXT_USHORT( p ); |
| OTL_UInt count = OTL_NEXT_USHORT( p ); |
| |
| |
| switch ( format ) |
| { |
| case 1: |
| { |
| OTL_UInt min = 0, max = count, mid, gindex; |
| |
| |
| table += 4; |
| while ( min < max ) |
| { |
| mid = ( min + max ) >> 1; |
| p = table + 2 * mid; |
| gindex = OTL_PEEK_USHORT( p ); |
| |
| if ( glyph_index == gindex ) |
| return (OTL_Int)mid; |
| |
| if ( glyph_index < gindex ) |
| max = mid; |
| else |
| min = mid + 1; |
| } |
| } |
| break; |
| |
| case 2: |
| { |
| OTL_UInt min = 0, max = count, mid; |
| OTL_UInt start, end, delta, start_cover; |
| |
| |
| table += 4; |
| while ( min < max ) |
| { |
| mid = ( min + max ) >> 1; |
| p = table + 6 * mid; |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| |
| if ( glyph_index < start ) |
| max = mid; |
| else if ( glyph_index > end ) |
| min = mid + 1; |
| else |
| return (OTL_Int)( glyph_index + OTL_NEXT_USHORT( p ) - start ); |
| } |
| } |
| break; |
| |
| default: |
| ; |
| } |
| |
| return -1; |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** CLASS DEFINITION TABLE *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_class_definition_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt format; |
| |
| |
| if ( p + 4 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| format = OTL_NEXT_USHORT( p ); |
| switch ( format ) |
| { |
| case 1: |
| { |
| OTL_UInt count, start = OTL_NEXT_USHORT( p ); |
| |
| |
| if ( p + 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| count = OTL_NEXT_USHORT( p ); |
| |
| if ( p + count * 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| /* XXX: check glyph indices */ |
| } |
| break; |
| |
| case 2: |
| { |
| OTL_UInt n, num_ranges = OTL_NEXT_USHORT( p ); |
| OTL_UInt start, end, value, last = 0; |
| |
| |
| if ( p + num_ranges * 6 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| for ( n = 0; n < num_ranges; n++ ) |
| { |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| value = OTL_NEXT_USHORT( p ); /* ignored */ |
| |
| if ( start > end || ( n > 0 && start <= last ) ) |
| OTL_INVALID_DATA; |
| |
| last = end; |
| } |
| } |
| break; |
| |
| default: |
| OTL_INVALID_FORMAT; |
| } |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_class_definition_get_value( OTL_Bytes table, |
| OTL_UInt glyph_index ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt format = OTL_NEXT_USHORT( p ); |
| |
| |
| switch ( format ) |
| { |
| case 1: |
| { |
| OTL_UInt start = OTL_NEXT_USHORT( p ); |
| OTL_UInt count = OTL_NEXT_USHORT( p ); |
| OTL_UInt idx = (OTL_UInt)( glyph_index - start ); |
| |
| |
| if ( idx < count ) |
| { |
| p += 2 * idx; |
| return OTL_PEEK_USHORT( p ); |
| } |
| } |
| break; |
| |
| case 2: |
| { |
| OTL_UInt count = OTL_NEXT_USHORT( p ); |
| OTL_UInt min = 0, max = count, mid, gindex; |
| |
| |
| table += 4; |
| while ( min < max ) |
| { |
| mid = ( min + max ) >> 1; |
| p = table + 6 * mid; |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| |
| if ( glyph_index < start ) |
| max = mid; |
| else if ( glyph_index > end ) |
| min = mid + 1; |
| else |
| return OTL_PEEK_USHORT( p ); |
| } |
| } |
| break; |
| |
| default: |
| ; |
| } |
| |
| return 0; |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** DEVICE TABLE *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_device_table_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt start, end, count, format, count; |
| |
| |
| if ( p + 8 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| format = OTL_NEXT_USHORT( p ); |
| |
| if ( format < 1 || format > 3 || end < start ) |
| OTL_INVALID_DATA; |
| |
| count = (OTL_UInt)( end - start + 1 ); |
| |
| if ( p + ( ( 1 << format ) * count ) / 8 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_device_table_get_start( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_device_table_get_end( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table + 2; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_Int ) |
| otl_device_table_get_delta( OTL_Bytes table, |
| OTL_UInt size ) |
| { |
| OTL_Bytes p = table; |
| OTL_Int result = 0; |
| OTL_UInt start, end, format, idx, value; |
| |
| |
| start = OTL_NEXT_USHORT( p ); |
| end = OTL_NEXT_USHORT( p ); |
| format = OTL_NEXT_USHORT( p ); |
| |
| if ( size >= start && size <= end ) |
| { |
| /* we could do that with clever bit operations, but a switch is */ |
| /* much simpler to understand and maintain */ |
| /* */ |
| switch ( format ) |
| { |
| case 1: |
| idx = (OTL_UInt)( ( size - start ) * 2 ); |
| p += idx / 16; |
| value = OTL_PEEK_USHORT( p ); |
| shift = idx & 15; |
| result = (OTL_Short)( value << shift ) >> ( 14 - shift ); |
| |
| break; |
| |
| case 2: |
| idx = (OTL_UInt)( ( size - start ) * 4 ); |
| p += idx / 16; |
| value = OTL_PEEK_USHORT( p ); |
| shift = idx & 15; |
| result = (OTL_Short)( value << shift ) >> ( 12 - shift ); |
| |
| break; |
| |
| case 3: |
| idx = (OTL_UInt)( ( size - start ) * 8 ); |
| p += idx / 16; |
| value = OTL_PEEK_USHORT( p ); |
| shift = idx & 15; |
| result = (OTL_Short)( value << shift ) >> ( 8 - shift ); |
| |
| break; |
| |
| default: |
| ; |
| } |
| } |
| |
| return result; |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** LOOKUP LISTS *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_lookup_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt num_tables; |
| |
| |
| if ( table + 6 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| p += 4; |
| num_tables = OTL_NEXT_USHORT( p ); |
| |
| if ( p + num_tables * 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| for ( ; num_tables > 0; num_tables-- ) |
| { |
| offset = OTL_NEXT_USHORT( p ); |
| |
| if ( table + offset >= valid->limit ) |
| OTL_INVALID_OFFSET; |
| } |
| |
| /* XXX: check sub-tables? */ |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_lookup_get_count( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table + 4; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_Bytes ) |
| otl_lookup_get_table( OTL_Bytes table, |
| OTL_UInt idx ) |
| { |
| OTL_Bytes p, result = NULL; |
| OTL_UInt count; |
| |
| |
| p = table + 4; |
| count = OTL_NEXT_USHORT( p ); |
| if ( idx < count ) |
| { |
| p += idx * 2; |
| result = table + OTL_PEEK_USHORT( p ); |
| } |
| |
| return result; |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** LOOKUP LISTS *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_lookup_list_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table, q; |
| OTL_UInt num_lookups, offset; |
| |
| |
| if ( p + 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| num_lookups = OTL_NEXT_USHORT( p ); |
| |
| if ( p + num_lookups * 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| for ( ; num_lookups > 0; num_lookups-- ) |
| { |
| offset = OTL_NEXT_USHORT( p ); |
| |
| otl_lookup_validate( table + offset, valid ); |
| } |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_lookup_list_get_count( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_Bytes ) |
| otl_lookup_list_get_lookup( OTL_Bytes table, |
| OTL_UInt idx ) |
| { |
| OTL_Bytes p, result = 0; |
| OTL_UInt count; |
| |
| |
| p = table; |
| count = OTL_NEXT_USHORT( p ); |
| if ( idx < count ) |
| { |
| p += idx * 2; |
| result = table + OTL_PEEK_USHORT( p ); |
| } |
| |
| return result; |
| } |
| |
| |
| OTL_LOCALDEF( OTL_Bytes ) |
| otl_lookup_list_get_table( OTL_Bytes table, |
| OTL_UInt lookup_index, |
| OTL_UInt table_index ) |
| { |
| OTL_Bytes result = NULL; |
| |
| |
| result = otl_lookup_list_get_lookup( table, lookup_index ); |
| if ( result ) |
| result = otl_lookup_get_table( result, table_index ); |
| |
| return result; |
| } |
| |
| |
| OTL_LOCALDEF( void ) |
| otl_lookup_list_foreach( OTL_Bytes table, |
| OTL_ForeachFunc func, |
| OTL_Pointer func_data ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt count = OTL_NEXT_USHORT( p ); |
| |
| |
| for ( ; count > 0; count-- ) |
| func( table + OTL_NEXT_USHORT( p ), func_data ); |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** FEATURES *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_feature_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt feat_params, num_lookups; |
| |
| |
| if ( p + 4 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| feat_params = OTL_NEXT_USHORT( p ); /* ignored */ |
| num_lookups = OTL_NEXT_USHORT( p ); |
| |
| if ( p + num_lookups * 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| /* XXX: check lookup indices */ |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_feature_get_count( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table + 4; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_feature_get_lookups( OTL_Bytes table, |
| OTL_UInt start, |
| OTL_UInt count, |
| OTL_UInt *lookups ) |
| { |
| OTL_Bytes p; |
| OTL_UInt num_features, result = 0; |
| |
| |
| p = table + 4; |
| num_features = OTL_NEXT_USHORT( p ); |
| |
| p += start * 2; |
| |
| for ( ; count > 0 && start < num_features; count--, start++ ) |
| { |
| lookups[0] = OTL_NEXT_USHORT(p); |
| lookups++; |
| result++; |
| } |
| |
| return result; |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** FEATURE LIST *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| OTL_LOCALDEF( void ) |
| otl_feature_list_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt num_features, offset; |
| |
| |
| if ( table + 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| num_features = OTL_NEXT_USHORT( p ); |
| |
| if ( p + num_features * 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| for ( ; num_features > 0; num_features-- ) |
| { |
| p += 4; /* skip tag */ |
| offset = OTL_NEXT_USHORT( p ); |
| |
| otl_feature_table_validate( table + offset, valid ); |
| } |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_feature_list_get_count( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_Bytes ) |
| otl_feature_list_get_feature( OTL_Bytes table, |
| OTL_UInt idx ) |
| { |
| OTL_Bytes p, result = NULL; |
| OTL_UInt count; |
| |
| |
| p = table; |
| count = OTL_NEXT_USHORT( p ); |
| |
| if ( idx < count ) |
| { |
| p += idx * 2; |
| result = table + OTL_PEEK_USHORT( p ); |
| } |
| |
| return result; |
| } |
| |
| |
| OTL_LOCALDEF( void ) |
| otl_feature_list_foreach( OTL_Bytes table, |
| OTL_ForeachFunc func, |
| OTL_Pointer func_data ) |
| { |
| OTL_Bytes p; |
| OTL_UInt count; |
| |
| |
| p = table; |
| count = OTL_NEXT_USHORT( p ); |
| |
| for ( ; count > 0; count-- ) |
| func( table + OTL_NEXT_USHORT( p ), func_data ); |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** LANGUAGE SYSTEM *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| |
| OTL_LOCALDEF( void ) |
| otl_lang_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt lookup_order; |
| OTL_UInt req_feature; |
| OTL_UInt num_features; |
| |
| |
| if ( table + 6 >= valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| lookup_order = OTL_NEXT_USHORT( p ); |
| req_feature = OTL_NEXT_USHORT( p ); |
| num_features = OTL_NEXT_USHORT( p ); |
| |
| /* XXX: check req_feature if not 0xFFFFU */ |
| |
| if ( p + 2 * num_features >= valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| /* XXX: check features indices! */ |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_lang_get_count( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table + 4; |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_lang_get_req_feature( OTL_Bytes table ) |
| { |
| OTL_Bytes p = table + 2; |
| |
| |
| return OTL_PEEK_USHORT( p ); |
| } |
| |
| |
| OTL_LOCALDEF( OTL_UInt ) |
| otl_lang_get_features( OTL_Bytes table, |
| OTL_UInt start, |
| OTL_UInt count, |
| OTL_UInt *features ) |
| { |
| OTL_Bytes p = table + 4; |
| OTL_UInt num_features = OTL_NEXT_USHORT( p ); |
| OTL_UInt result = 0; |
| |
| |
| p += start * 2; |
| |
| for ( ; count > 0 && start < num_features; start++, count-- ) |
| { |
| features[0] = OTL_NEXT_USHORT( p ); |
| features++; |
| result++; |
| } |
| |
| return result; |
| } |
| |
| |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** SCRIPTS *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| |
| OTL_LOCALDEF( void ) |
| otl_script_validate( OTL_Bytes table, |
| OTL_Validator valid ) |
| { |
| OTL_UInt default_lang; |
| OTL_Bytes p = table; |
| |
| |
| if ( table + 4 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| default_lang = OTL_NEXT_USHORT( p ); |
| num_langs = OTL_NEXT_USHORT( p ); |
| |
| if ( default_lang != 0 ) |
| { |
| if ( table + default_lang >= valid->limit ) |
| OTL_INVALID_OFFSET; |
| } |
| |
| if ( p + num_langs * 6 >= valid->limit ) |
| OTL_INVALID_OFFSET; |
| |
| for ( ; num_langs > 0; num_langs-- ) |
| { |
| OTL_UInt offset; |
| |
| |
| p += 4; /* skip tag */ |
| offset = OTL_NEXT_USHORT( p ); |
| |
| otl_lang_validate( table + offset, valid ); |
| } |
| } |
| |
| |
| OTL_LOCALDEF( void ) |
| otl_script_list_validate( OTL_Bytes list, |
| OTL_Validator valid ) |
| { |
| OTL_UInt num_scripts; |
| OTL_Bytes p = list; |
| |
| |
| if ( list + 2 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| num_scripts = OTL_NEXT_USHORT( p ); |
| |
| if ( p + num_scripts * 6 > valid->limit ) |
| OTL_INVALID_TOO_SHORT; |
| |
| for ( ; num_scripts > 0; num_scripts-- ) |
| { |
| OTL_UInt offset; |
| |
| |
| p += 4; /* skip tag */ |
| offset = OTL_NEXT_USHORT( p ); |
| |
| otl_script_table_validate( list + offset, valid ); |
| } |
| } |
| |
| |
| /*************************************************************************/ |
| /*************************************************************************/ |
| /***** *****/ |
| /***** LOOKUP LISTS *****/ |
| /***** *****/ |
| /*************************************************************************/ |
| /*************************************************************************/ |
| |
| static void |
| otl_lookup_table_validate( OTL_Bytes table, |
| OTL_UInt type_count, |
| OTL_ValidateFunc* type_funcs, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt lookup_type, lookup_flag, count; |
| OTL_ValidateFunc validate; |
| |
| OTL_CHECK( 6 ); |
| lookup_type = OTL_NEXT_USHORT( p ); |
| lookup_flag = OTL_NEXT_USHORT( p ); |
| count = OTL_NEXT_USHORT( p ); |
| |
| if ( lookup_type == 0 || lookup_type >= type_count ) |
| OTL_INVALID_DATA; |
| |
| validate = type_funcs[ lookup_type - 1 ]; |
| |
| OTL_CHECK( 2*count ); |
| for ( ; count > 0; count-- ) |
| validate( table + OTL_NEXT_USHORT( p ), valid ); |
| } |
| |
| |
| OTL_LOCALDEF( void ) |
| otl_lookup_list_validate( OTL_Bytes table, |
| OTL_UInt type_count, |
| OTL_ValidateFunc* type_funcs, |
| OTL_Validator valid ) |
| { |
| OTL_Bytes p = table; |
| OTL_UInt count; |
| |
| OTL_CHECK( 2 ); |
| count = OTL_NEXT_USHORT( p ); |
| |
| OTL_CHECK( 2*count ); |
| for ( ; count > 0; count-- ) |
| otl_lookup_table_validate( table + OTL_NEXT_USHORT( p ), |
| type_count, type_funcs, valid ); |
| } |
| |
| /* END */ |