update for HEAD-2003050101
[reactos.git] / lib / freetype / src / otlayout / otlcommn.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  otlcommn.c                                                             */
4 /*                                                                         */
5 /*    OpenType layout support, common tables (body).                       */
6 /*                                                                         */
7 /*  Copyright 2002 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 "otlayout.h"
20
21
22  /*************************************************************************/
23  /*************************************************************************/
24  /*****                                                               *****/
25  /*****                       COVERAGE TABLE                          *****/
26  /*****                                                               *****/
27  /*************************************************************************/
28  /*************************************************************************/
29
30   OTL_LOCALDEF( void )
31   otl_coverage_validate( OTL_Bytes      table,
32                          OTL_Validator  valid )
33   {
34     OTL_Bytes  p;
35     OTL_UInt   format;
36
37
38     if ( table + 4 > valid->limit )
39       OTL_INVALID_TOO_SHORT;
40
41     format = OTL_NEXT_USHORT( p );
42     switch ( format )
43     {
44     case 1:
45       {
46         OTL_UInt  count = OTL_NEXT_USHORT( p );
47
48
49         if ( p + count * 2 >= valid->limit )
50           OTL_INVALID_TOO_SHORT;
51
52         /* XXX: check glyph indices */
53       }
54       break;
55
56     case 2:
57       {
58         OTL_UInt  n, num_ranges = OTL_NEXT_USHORT( p );
59         OTL_UInt  start, end, start_cover, total = 0, last = 0;
60
61
62         if ( p + num_ranges * 6 >= valid->limit )
63           OTL_INVALID_TOO_SHORT;
64
65         for ( n = 0; n < num_ranges; n++ )
66         {
67           start       = OTL_NEXT_USHORT( p );
68           end         = OTL_NEXT_USHORT( p );
69           start_cover = OTL_NEXT_USHORT( p );
70
71           if ( start > end || start_cover != total )
72             OTL_INVALID_DATA;
73
74           if ( n > 0 && start <= last )
75             OTL_INVALID_DATA;
76
77           total += end - start + 1;
78           last   = end;
79         }
80       }
81       break;
82
83     default:
84       OTL_INVALID_FORMAT;
85     }
86   }
87
88
89   OTL_LOCALDEF( OTL_UInt )
90   otl_coverage_get_count( OTL_Bytes  table )
91   {
92     OTL_Bytes  p      = table;
93     OTL_UInt   format = OTL_NEXT_USHORT( p );
94     OTL_UInt   count  = OTL_NEXT_USHORT( p );
95     OTL_UInt   result = 0;
96
97
98     switch ( format )
99     {
100     case 1:
101       return count;
102
103     case 2:
104       {
105         OTL_UInt  start, end;
106
107
108         for ( ; count > 0; count-- )
109         {
110           start = OTL_NEXT_USHORT( p );
111           end   = OTL_NEXT_USHORT( p );
112           p    += 2;                    /* skip start_index */
113
114           result += end - start + 1;
115         }
116       }
117       break;
118
119     default:
120       ;
121     }
122
123     return result;
124   }
125
126
127   OTL_LOCALDEF( OTL_Int )
128   otl_coverage_get_index( OTL_Bytes  table,
129                           OTL_UInt   glyph_index )
130   {
131     OTL_Bytes  p      = table;
132     OTL_UInt   format = OTL_NEXT_USHORT( p );
133     OTL_UInt   count  = OTL_NEXT_USHORT( p );
134
135
136     switch ( format )
137     {
138     case 1:
139       {
140         OTL_UInt  min = 0, max = count, mid, gindex;
141
142
143         table += 4;
144         while ( min < max )
145         {
146           mid    = ( min + max ) >> 1;
147           p      = table + 2 * mid;
148           gindex = OTL_PEEK_USHORT( p );
149
150           if ( glyph_index == gindex )
151             return (OTL_Int)mid;
152
153           if ( glyph_index < gindex )
154             max = mid;
155           else
156             min = mid + 1;
157         }
158       }
159       break;
160
161     case 2:
162       {
163         OTL_UInt  min = 0, max = count, mid;
164         OTL_UInt  start, end, delta, start_cover;
165
166
167         table += 4;
168         while ( min < max )
169         {
170           mid    = ( min + max ) >> 1;
171           p      = table + 6 * mid;
172           start  = OTL_NEXT_USHORT( p );
173           end    = OTL_NEXT_USHORT( p );
174
175           if ( glyph_index < start )
176             max = mid;
177           else if ( glyph_index > end )
178             min = mid + 1;
179           else
180             return (OTL_Int)( glyph_index + OTL_NEXT_USHORT( p ) - start );
181         }
182       }
183       break;
184
185     default:
186       ;
187     }
188
189     return -1;
190   }
191
192
193   /*************************************************************************/
194   /*************************************************************************/
195   /*****                                                               *****/
196   /*****                  CLASS DEFINITION TABLE                       *****/
197   /*****                                                               *****/
198   /*************************************************************************/
199   /*************************************************************************/
200
201   OTL_LOCALDEF( void )
202   otl_class_definition_validate( OTL_Bytes      table,
203                                  OTL_Validator  valid )
204   {
205     OTL_Bytes  p = table;
206     OTL_UInt   format;
207
208
209     if ( p + 4 > valid->limit )
210       OTL_INVALID_TOO_SHORT;
211
212     format = OTL_NEXT_USHORT( p );
213     switch ( format )
214     {
215     case 1:
216       {
217         OTL_UInt  count, start = OTL_NEXT_USHORT( p );
218
219
220         if ( p + 2 > valid->limit )
221           OTL_INVALID_TOO_SHORT;
222
223         count = OTL_NEXT_USHORT( p );
224
225         if ( p + count * 2 > valid->limit )
226           OTL_INVALID_TOO_SHORT;
227
228         /* XXX: check glyph indices */
229       }
230       break;
231
232     case 2:
233       {
234         OTL_UInt  n, num_ranges = OTL_NEXT_USHORT( p );
235         OTL_UInt  start, end, value, last = 0;
236
237
238         if ( p + num_ranges * 6 > valid->limit )
239           OTL_INVALID_TOO_SHORT;
240
241         for ( n = 0; n < num_ranges; n++ )
242         {
243           start = OTL_NEXT_USHORT( p );
244           end   = OTL_NEXT_USHORT( p );
245           value = OTL_NEXT_USHORT( p );  /* ignored */
246
247           if ( start > end || ( n > 0 && start <= last ) )
248             OTL_INVALID_DATA;
249
250           last = end;
251         }
252       }
253       break;
254
255     default:
256       OTL_INVALID_FORMAT;
257     }
258   }
259
260
261   OTL_LOCALDEF( OTL_UInt )
262   otl_class_definition_get_value( OTL_Bytes  table,
263                                   OTL_UInt   glyph_index )
264   {
265     OTL_Bytes  p      = table;
266     OTL_UInt   format = OTL_NEXT_USHORT( p );
267
268
269     switch ( format )
270     {
271     case 1:
272       {
273         OTL_UInt  start = OTL_NEXT_USHORT( p );
274         OTL_UInt  count = OTL_NEXT_USHORT( p );
275         OTL_UInt  idx   = (OTL_UInt)( glyph_index - start );
276
277
278         if ( idx < count )
279         {
280           p += 2 * idx;
281           return OTL_PEEK_USHORT( p );
282         }
283       }
284       break;
285
286     case 2:
287       {
288         OTL_UInt  count = OTL_NEXT_USHORT( p );
289         OTL_UInt  min = 0, max = count, mid, gindex;
290
291
292         table += 4;
293         while ( min < max )
294         {
295           mid   = ( min + max ) >> 1;
296           p     = table + 6 * mid;
297           start = OTL_NEXT_USHORT( p );
298           end   = OTL_NEXT_USHORT( p );
299
300           if ( glyph_index < start )
301             max = mid;
302           else if ( glyph_index > end )
303             min = mid + 1;
304           else
305             return OTL_PEEK_USHORT( p );
306         }
307       }
308       break;
309
310     default:
311       ;
312     }
313
314     return 0;
315   }
316
317
318   /*************************************************************************/
319   /*************************************************************************/
320   /*****                                                               *****/
321   /*****                      DEVICE TABLE                             *****/
322   /*****                                                               *****/
323   /*************************************************************************/
324   /*************************************************************************/
325
326   OTL_LOCALDEF( void )
327   otl_device_table_validate( OTL_Bytes      table,
328                              OTL_Validator  valid )
329   {
330     OTL_Bytes  p = table;
331     OTL_UInt   start, end, count, format, count;
332
333
334     if ( p + 8 > valid->limit )
335       OTL_INVALID_TOO_SHORT;
336
337     start  = OTL_NEXT_USHORT( p );
338     end    = OTL_NEXT_USHORT( p );
339     format = OTL_NEXT_USHORT( p );
340
341     if ( format < 1 || format > 3 || end < start )
342       OTL_INVALID_DATA;
343
344     count = (OTL_UInt)( end - start + 1 );
345
346     if ( p + ( ( 1 << format ) * count ) / 8 > valid->limit )
347       OTL_INVALID_TOO_SHORT;
348   }
349
350
351   OTL_LOCALDEF( OTL_UInt )
352   otl_device_table_get_start( OTL_Bytes  table )
353   {
354     OTL_Bytes  p = table;
355
356
357     return OTL_PEEK_USHORT( p );
358   }
359
360
361   OTL_LOCALDEF( OTL_UInt )
362   otl_device_table_get_end( OTL_Bytes  table )
363   {
364     OTL_Bytes  p = table + 2;
365
366
367     return OTL_PEEK_USHORT( p );
368   }
369
370
371   OTL_LOCALDEF( OTL_Int )
372   otl_device_table_get_delta( OTL_Bytes  table,
373                               OTL_UInt   size )
374   {
375     OTL_Bytes  p = table;
376     OTL_Int    result = 0;
377     OTL_UInt   start, end, format, idx, value;
378
379
380     start  = OTL_NEXT_USHORT( p );
381     end    = OTL_NEXT_USHORT( p );
382     format = OTL_NEXT_USHORT( p );
383
384     if ( size >= start && size <= end )
385     {
386       /* we could do that with clever bit operations, but a switch is */
387       /* much simpler to understand and maintain                      */
388       /*                                                              */
389       switch ( format )
390       {
391       case 1:
392         idx    = (OTL_UInt)( ( size - start ) * 2 );
393         p     += idx / 16;
394         value  = OTL_PEEK_USHORT( p );
395         shift  = idx & 15;
396         result = (OTL_Short)( value << shift ) >> ( 14 - shift );
397
398         break;
399
400       case 2:
401         idx    = (OTL_UInt)( ( size - start ) * 4 );
402         p     += idx / 16;
403         value  = OTL_PEEK_USHORT( p );
404         shift  = idx & 15;
405         result = (OTL_Short)( value << shift ) >> ( 12 - shift );
406
407         break;
408
409       case 3:
410         idx    = (OTL_UInt)( ( size - start ) * 8 );
411         p     += idx / 16;
412         value  = OTL_PEEK_USHORT( p );
413         shift  = idx & 15;
414         result = (OTL_Short)( value << shift ) >> ( 8 - shift );
415
416         break;
417
418       default:
419         ;
420       }
421     }
422
423     return result;
424   }
425
426
427   /*************************************************************************/
428   /*************************************************************************/
429   /*****                                                               *****/
430   /*****                      LOOKUP LISTS                             *****/
431   /*****                                                               *****/
432   /*************************************************************************/
433   /*************************************************************************/
434
435   OTL_LOCALDEF( void )
436   otl_lookup_validate( OTL_Bytes      table,
437                        OTL_Validator  valid )
438   {
439     OTL_Bytes  p = table;
440     OTL_UInt   num_tables;
441
442
443     if ( table + 6 > valid->limit )
444       OTL_INVALID_TOO_SHORT;
445
446     p += 4;
447     num_tables = OTL_NEXT_USHORT( p );
448
449     if ( p + num_tables * 2 > valid->limit )
450       OTL_INVALID_TOO_SHORT;
451
452     for ( ; num_tables > 0; num_tables-- )
453     {
454       offset = OTL_NEXT_USHORT( p );
455
456       if ( table + offset >= valid->limit )
457         OTL_INVALID_OFFSET;
458     }
459
460     /* XXX: check sub-tables? */
461   }
462
463
464   OTL_LOCALDEF( OTL_UInt )
465   otl_lookup_get_count( OTL_Bytes  table )
466   {
467     OTL_Bytes  p = table + 4;
468
469
470     return OTL_PEEK_USHORT( p );
471   }
472
473
474   OTL_LOCALDEF( OTL_Bytes )
475   otl_lookup_get_table( OTL_Bytes  table,
476                         OTL_UInt   idx )
477   {
478     OTL_Bytes  p, result = NULL;
479     OTL_UInt   count;
480
481
482     p     = table + 4;
483     count = OTL_NEXT_USHORT( p );
484     if ( idx < count )
485     {
486       p     += idx * 2;
487       result = table + OTL_PEEK_USHORT( p );
488     }
489
490     return result;
491   }
492
493
494   /*************************************************************************/
495   /*************************************************************************/
496   /*****                                                               *****/
497   /*****                      LOOKUP LISTS                             *****/
498   /*****                                                               *****/
499   /*************************************************************************/
500   /*************************************************************************/
501
502   OTL_LOCALDEF( void )
503   otl_lookup_list_validate( OTL_Bytes      table,
504                             OTL_Validator  valid )
505   {
506     OTL_Bytes  p = table, q;
507     OTL_UInt   num_lookups, offset;
508
509
510     if ( p + 2 > valid->limit )
511       OTL_INVALID_TOO_SHORT;
512
513     num_lookups = OTL_NEXT_USHORT( p );
514
515     if ( p + num_lookups * 2 > valid->limit )
516       OTL_INVALID_TOO_SHORT;
517
518     for ( ; num_lookups > 0; num_lookups-- )
519     {
520       offset = OTL_NEXT_USHORT( p );
521
522       otl_lookup_validate( table + offset, valid );
523     }
524   }
525
526
527   OTL_LOCALDEF( OTL_UInt )
528   otl_lookup_list_get_count( OTL_Bytes  table )
529   {
530     OTL_Bytes  p = table;
531
532
533     return OTL_PEEK_USHORT( p );
534   }
535
536
537   OTL_LOCALDEF( OTL_Bytes )
538   otl_lookup_list_get_lookup( OTL_Bytes  table,
539                               OTL_UInt   idx )
540   {
541     OTL_Bytes  p, result = 0;
542     OTL_UInt   count;
543
544
545     p     = table;
546     count = OTL_NEXT_USHORT( p );
547     if ( idx < count )
548     {
549       p     += idx * 2;
550       result = table + OTL_PEEK_USHORT( p );
551     }
552
553     return result;
554   }
555
556
557   OTL_LOCALDEF( OTL_Bytes )
558   otl_lookup_list_get_table( OTL_Bytes  table,
559                              OTL_UInt   lookup_index,
560                              OTL_UInt   table_index )
561   {
562     OTL_Bytes  result = NULL;
563
564
565     result = otl_lookup_list_get_lookup( table, lookup_index );
566     if ( result )
567       result = otl_lookup_get_table( result, table_index );
568
569     return result;
570   }
571
572
573   OTL_LOCALDEF( void )
574   otl_lookup_list_foreach( OTL_Bytes        table,
575                            OTL_ForeachFunc  func,
576                            OTL_Pointer      func_data )
577   {
578     OTL_Bytes  p     = table;
579     OTL_UInt   count = OTL_NEXT_USHORT( p );
580
581
582     for ( ; count > 0; count-- )
583       func( table + OTL_NEXT_USHORT( p ), func_data );
584   }
585
586
587   /*************************************************************************/
588   /*************************************************************************/
589   /*****                                                               *****/
590   /*****                        FEATURES                               *****/
591   /*****                                                               *****/
592   /*************************************************************************/
593   /*************************************************************************/
594
595   OTL_LOCALDEF( void )
596   otl_feature_validate( OTL_Bytes      table,
597                         OTL_Validator  valid )
598   {
599     OTL_Bytes  p = table;
600     OTL_UInt   feat_params, num_lookups;
601
602
603     if ( p + 4 > valid->limit )
604       OTL_INVALID_TOO_SHORT;
605
606     feat_params = OTL_NEXT_USHORT( p );  /* ignored */
607     num_lookups = OTL_NEXT_USHORT( p );
608
609     if ( p + num_lookups * 2 > valid->limit )
610       OTL_INVALID_TOO_SHORT;
611
612     /* XXX: check lookup indices */
613   }
614
615
616   OTL_LOCALDEF( OTL_UInt )
617   otl_feature_get_count( OTL_Bytes  table )
618   {
619     OTL_Bytes  p = table + 4;
620
621
622     return OTL_PEEK_USHORT( p );
623   }
624
625
626   OTL_LOCALDEF( OTL_UInt )
627   otl_feature_get_lookups( OTL_Bytes  table,
628                            OTL_UInt   start,
629                            OTL_UInt   count,
630                            OTL_UInt  *lookups )
631   {
632     OTL_Bytes  p;
633     OTL_UInt   num_features, result = 0;
634
635
636     p            = table + 4;
637     num_features = OTL_NEXT_USHORT( p );
638
639     p += start * 2;
640
641     for ( ; count > 0 && start < num_features; count--, start++ )
642     {
643       lookups[0] = OTL_NEXT_USHORT(p);
644       lookups++;
645       result++;
646     }
647
648     return result;
649   }
650
651
652   /*************************************************************************/
653   /*************************************************************************/
654   /*****                                                               *****/
655   /*****                        FEATURE LIST                           *****/
656   /*****                                                               *****/
657   /*************************************************************************/
658   /*************************************************************************/
659
660   OTL_LOCALDEF( void )
661   otl_feature_list_validate( OTL_Bytes      table,
662                              OTL_Validator  valid )
663   {
664     OTL_Bytes  p = table;
665     OTL_UInt   num_features, offset;
666
667
668     if ( table + 2 > valid->limit )
669       OTL_INVALID_TOO_SHORT;
670
671     num_features = OTL_NEXT_USHORT( p );
672
673     if ( p + num_features * 2 > valid->limit )
674       OTL_INVALID_TOO_SHORT;
675
676     for ( ; num_features > 0; num_features-- )
677     {
678       p     += 4;                       /* skip tag */
679       offset = OTL_NEXT_USHORT( p );
680
681       otl_feature_table_validate( table + offset, valid );
682     }
683   }
684
685
686   OTL_LOCALDEF( OTL_UInt )
687   otl_feature_list_get_count( OTL_Bytes  table )
688   {
689     OTL_Bytes  p = table;
690
691
692     return OTL_PEEK_USHORT( p );
693   }
694
695
696   OTL_LOCALDEF( OTL_Bytes )
697   otl_feature_list_get_feature( OTL_Bytes  table,
698                                 OTL_UInt   idx )
699   {
700     OTL_Bytes  p, result = NULL;
701     OTL_UInt   count;
702
703
704     p     = table;
705     count = OTL_NEXT_USHORT( p );
706
707     if ( idx < count )
708     {
709       p     += idx * 2;
710       result = table + OTL_PEEK_USHORT( p );
711     }
712
713     return result;
714   }
715
716
717   OTL_LOCALDEF( void )
718   otl_feature_list_foreach( OTL_Bytes        table,
719                             OTL_ForeachFunc  func,
720                             OTL_Pointer      func_data )
721   {
722     OTL_Bytes  p;
723     OTL_UInt   count;
724
725
726     p = table;
727     count = OTL_NEXT_USHORT( p );
728
729     for ( ; count > 0; count-- )
730       func( table + OTL_NEXT_USHORT( p ), func_data );
731   }
732
733
734   /*************************************************************************/
735   /*************************************************************************/
736   /*****                                                               *****/
737   /*****                       LANGUAGE SYSTEM                         *****/
738   /*****                                                               *****/
739   /*************************************************************************/
740   /*************************************************************************/
741
742
743   OTL_LOCALDEF( void )
744   otl_lang_validate( OTL_Bytes      table,
745                      OTL_Validator  valid )
746   {
747     OTL_Bytes  p = table;
748     OTL_UInt   lookup_order;
749     OTL_UInt   req_feature;
750     OTL_UInt   num_features;
751
752
753     if ( table + 6 >= valid->limit )
754       OTL_INVALID_TOO_SHORT;
755
756     lookup_order = OTL_NEXT_USHORT( p );
757     req_feature  = OTL_NEXT_USHORT( p );
758     num_features = OTL_NEXT_USHORT( p );
759
760     /* XXX: check req_feature if not 0xFFFFU */
761
762     if ( p + 2 * num_features >= valid->limit )
763       OTL_INVALID_TOO_SHORT;
764
765     /* XXX: check features indices! */
766   }
767
768
769   OTL_LOCALDEF( OTL_UInt )
770   otl_lang_get_count( OTL_Bytes  table )
771   {
772     OTL_Bytes  p = table + 4;
773
774     return OTL_PEEK_USHORT( p );
775   }
776
777
778   OTL_LOCALDEF( OTL_UInt )
779   otl_lang_get_req_feature( OTL_Bytes  table )
780   {
781     OTL_Bytes  p = table + 2;
782
783
784     return OTL_PEEK_USHORT( p );
785   }
786
787
788   OTL_LOCALDEF( OTL_UInt )
789   otl_lang_get_features( OTL_Bytes  table,
790                          OTL_UInt   start,
791                          OTL_UInt   count,
792                          OTL_UInt  *features )
793   {
794     OTL_Bytes  p            = table + 4;
795     OTL_UInt   num_features = OTL_NEXT_USHORT( p );
796     OTL_UInt   result       = 0;
797
798
799     p += start * 2;
800
801     for ( ; count > 0 && start < num_features; start++, count-- )
802     {
803       features[0] = OTL_NEXT_USHORT( p );
804       features++;
805       result++;
806     }
807
808     return result;
809   }
810
811
812
813
814   /*************************************************************************/
815   /*************************************************************************/
816   /*****                                                               *****/
817   /*****                           SCRIPTS                             *****/
818   /*****                                                               *****/
819   /*************************************************************************/
820   /*************************************************************************/
821
822
823   OTL_LOCALDEF( void )
824   otl_script_validate( OTL_Bytes      table,
825                        OTL_Validator  valid )
826   {
827     OTL_UInt   default_lang;
828     OTL_Bytes  p = table;
829
830
831     if ( table + 4 > valid->limit )
832       OTL_INVALID_TOO_SHORT;
833
834     default_lang = OTL_NEXT_USHORT( p );
835     num_langs    = OTL_NEXT_USHORT( p );
836
837     if ( default_lang != 0 )
838     {
839       if ( table + default_lang >= valid->limit )
840         OTL_INVALID_OFFSET;
841     }
842
843     if ( p + num_langs * 6 >= valid->limit )
844       OTL_INVALID_OFFSET;
845
846     for ( ; num_langs > 0; num_langs-- )
847     {
848       OTL_UInt  offset;
849
850
851       p     += 4;  /* skip tag */
852       offset = OTL_NEXT_USHORT( p );
853
854       otl_lang_validate( table + offset, valid );
855     }
856   }
857
858
859   OTL_LOCALDEF( void )
860   otl_script_list_validate( OTL_Bytes      list,
861                             OTL_Validator  valid )
862   {
863     OTL_UInt   num_scripts;
864     OTL_Bytes  p = list;
865
866
867     if ( list + 2 > valid->limit )
868       OTL_INVALID_TOO_SHORT;
869
870     num_scripts = OTL_NEXT_USHORT( p );
871
872     if ( p + num_scripts * 6 > valid->limit )
873       OTL_INVALID_TOO_SHORT;
874
875     for ( ; num_scripts > 0; num_scripts-- )
876     {
877       OTL_UInt  offset;
878
879
880       p     += 4;                       /* skip tag */
881       offset = OTL_NEXT_USHORT( p );
882
883       otl_script_table_validate( list + offset, valid );
884     }
885   }
886
887
888   /*************************************************************************/
889   /*************************************************************************/
890   /*****                                                               *****/
891   /*****                         LOOKUP LISTS                          *****/
892   /*****                                                               *****/
893   /*************************************************************************/
894   /*************************************************************************/
895
896   static void
897   otl_lookup_table_validate( OTL_Bytes          table,
898                              OTL_UInt           type_count,
899                              OTL_ValidateFunc*  type_funcs,
900                              OTL_Validator      valid )
901   {
902     OTL_Bytes         p = table;
903     OTL_UInt          lookup_type, lookup_flag, count;
904     OTL_ValidateFunc  validate;
905
906     OTL_CHECK( 6 );
907     lookup_type = OTL_NEXT_USHORT( p );
908     lookup_flag = OTL_NEXT_USHORT( p );
909     count       = OTL_NEXT_USHORT( p );
910
911     if ( lookup_type == 0 || lookup_type >= type_count )
912       OTL_INVALID_DATA;
913
914     validate = type_funcs[ lookup_type - 1 ];
915
916     OTL_CHECK( 2*count );
917     for ( ; count > 0; count-- )
918       validate( table + OTL_NEXT_USHORT( p ), valid );
919   }
920
921
922   OTL_LOCALDEF( void )
923   otl_lookup_list_validate( OTL_Bytes          table,
924                             OTL_UInt           type_count,
925                             OTL_ValidateFunc*  type_funcs,
926                             OTL_Validator      valid )
927   {
928     OTL_Bytes  p = table;
929     OTL_UInt   count;
930
931     OTL_CHECK( 2 );
932     count = OTL_NEXT_USHORT( p );
933
934     OTL_CHECK( 2*count );
935     for ( ; count > 0; count-- )
936       otl_lookup_table_validate( table + OTL_NEXT_USHORT( p ),
937                                  type_count, type_funcs, valid );
938   }
939
940 /* END */