File: tdatainfo.c

package info (click to toggle)
libhdf4 4.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 29,892 kB
  • sloc: ansic: 128,688; sh: 14,969; fortran: 12,444; java: 5,864; xml: 1,305; makefile: 900; yacc: 678; pascal: 418; perl: 360; javascript: 203; lex: 163; csh: 41
file content (1494 lines) | stat: -rw-r--r-- 62,629 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF.  The full HDF copyright notice, including       *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/****************************************************************************
 * tdatainfo.c - tests the functions VSgetdatainfo, ANgetdatainfo,
 *			GRgetdatainfo, and Hgetntinfo
 * Structure of the file:
 *    test_datainfo - test driver
 *	test_simple_vs   - test VSgetdatainfo with data stored in one
 *			   contiguous block
 *	test_append_vs   - test VSgetdatainfo with data stored in linked blocks
 *	test_annotation  - test ANgetdatainfo
 *	test_oneblock_ri - test GRgetdatainfo with images stored in one
 *			   contiguous block, with and without compression
 *	test_dfr8_24     - test GRgetdatainfo with RI8 and RI24
 *	test_getntinfo   - test Hgetntinfo
 ****************************************************************************/

#include "hdf.h"
#include "tdatainfo.h"
#include "tproto.h"

static void test_simple_vs();
static void test_append_vs();
static void test_annotation();
static void test_oneblock_ri();
static void test_dfr8_24();
static void test_getntinfo();
static void test_getpalinfo();

/***********************************************************************
  NOTE: At this time, some of the offsets in these tests are verified
        by hard-coding.  When adding new data to the files in exiting
        tests, please either add data at the bottom of the files or
        change the hard-coded offsets appropriately, using the values
        from the error messages.  However, you'll need to verify the
        correctness of these values first using the command 'od' on
        the hdf file.
*************************************************************************/

/* Structure to hold annotation datainfo temporarily */
typedef struct {
    char  anntext[100]; /* values of the annotation */
    int32 offset;       /* offset of data block */
    int32 length;       /* length of data block */
} t_ann_info_t;

/* Functions to access t_hdfdatainfo_t, defined in ./tdatainfo.h */

/* alloc_info is a utility function that allocates t_hdf_datainfo_t's members*/
intn
alloc_info(t_hdf_datainfo_t *info, uintn info_count)
{
    info->offsets = (int32 *)malloc(info_count * sizeof(int32));
    if (info->offsets == NULL)
        return -1;
    info->lengths = (int32 *)malloc(info_count * sizeof(int32));
    if (info->lengths == NULL)
        return -1;
    return 0;
}

void
free_info(t_hdf_datainfo_t *info)
{
    if (info != NULL) {
        free(info->offsets);
        free(info->lengths);
    }
}

/****************************************************************************
   Name: test_simple_vs() - tests non-special Vdatas

   Description:
        This routine creates and writes contiguous data to vdatas and verifies
        some data and data information with VSgetdatainfo.  The tests include
        the following vdatas:
        - a single field vdata with int32 values
        - a multiple field/multiple order vdata with all int32 values
        - a single field vdata with character values
        Only the character vdata's values are verified against the original
        buffer.  The other two were verified by examining the hdf file using
        od. (Todo 1)
   BMR - Jul 2010
 ****************************************************************************/
#define SIMPLE_FILE      "tdatainfo_simple.hdf" /* data file */
#define NONSPECIAL_VS    "Non-Special Vdata"
#define CONTCLASS_NAME   "Contiguous Vdata"
#define LINKED_BLOCK     "Linked-block Vdata"
#define FIELD1_NAME      "Field1" /* contains three integers */
#define FIELD2_NAME      "Field2" /* contains one integer */
#define FIELD3_NAME      "Field3" /* contains two integers */
#define FIELD_NAME_LIST  "Field1,Field2,Field3"
#define ORDER_1          3                             /* order of first field of 1st vdata */
#define ORDER_2          1                             /* order of second field of 1st vdata */
#define ORDER_3          2                             /* order of third field of 1st vdata */
#define BLOCK_SIZE       80                            /* arbitrary number for block size */
#define NUM_BLOCKS       8                             /* arbitrary number for number of blocks */
#define N_VALS_PER_REC_1 1                             /* # of values per record in single vdata */
#define N_VALS_PER_REC_2 (ORDER_1 + ORDER_2 + ORDER_3) /* # of vals/rec. in multiple vdata */
#define N_RECORDS                                                                                            \
    5 /* number of records to be written to the                                                              \
         vdatas at every write */
static void
test_simple_vs()
{
    int32 fid,                                  /* File ID */
        vsid,                                   /* Vdata ID */
        vs_ref,                                 /* Vdata ref# */
        n_records,                              /* number of records actually written to vdata */
        data_buf0[N_RECORDS][N_VALS_PER_REC_1], /* for single vdata's data */
        data_buf1[N_RECORDS][N_VALS_PER_REC_2]; /* for multiple vdata's data*/
    char  data_buf2[N_RECORDS] = {'H', '4', 'M', 'A', 'P'};
    int16 rec_num;        /* current record number */
    int32 offset, length; /* offset/length buffers for single block of data */
    intn  n_blocks;       /* number of blocks a vdata has */
    int32 status;         /* Status values from routines */
    intn  status_n;       /* Status values from routines */

    /* Open the HDF file and initialize the interface. */
    fid = Hopen(SIMPLE_FILE, DFACC_CREATE, 0);
    CHECK_VOID(fid, FAIL, "Hopen");
    status = Vstart(fid);
    CHECK_VOID(status, FAIL, "Vstart");

    /* Create and write to the first vdata using high-level func VHstoredata */
    for (rec_num = 0; rec_num < N_RECORDS; rec_num++)
        data_buf0[rec_num][0] = 5 + rec_num;

    vs_ref = VHstoredata(fid, "Only field", (const uint8 *)data_buf0, N_RECORDS, DFNT_INT32,
                         "One Field One Order", CONTCLASS_NAME);

    /*
     * Get access to the vdata just created then get and verify offset/length
     * of its data
     */

    vsid = VSattach(fid, vs_ref, "w");
    CHECK_VOID(vsid, FAIL, "VSattach");

    /* Get the number of data blocks first, should be 1 */
    n_blocks = VSgetdatainfo(vsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    VERIFY_VOID(n_blocks, 1, "VSgetdatainfo");

    /* Get the offset/length of the data, should be 294/20 */
    n_blocks = VSgetdatainfo(vsid, 0, n_blocks, &offset, &length);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");

    /* Verify offset/length */
    VERIFY_VOID(offset, 294, "VSgetdatainfo offset from 'One Field One Order'");
    VERIFY_VOID(length, 20, "VSgetdatainfo length from 'One Field One Order'");

    status = VSdetach(vsid);
    CHECK_VOID(status, FAIL, "VSdetach");

    /*
     * Create a multi-field/multi-order vdata, named NONSPECIAL_VS, in class
     * CONTCLASS_NAME, write data to it, then get and verify its data's
     * offsets/lengths
     */
    vsid = VSattach(fid, -1, "w");
    CHECK_VOID(vsid, FAIL, "VSattach");

    /* Set name and class name of the vdata. */
    status = VSsetname(vsid, NONSPECIAL_VS);
    CHECK_VOID(status, FAIL, "VSsetname");
    status = VSsetclass(vsid, CONTCLASS_NAME);
    CHECK_VOID(status, FAIL, "VSsetclass");

    /* Record its reference number for later access before detaching it */
    vs_ref = VSQueryref(vsid);
    CHECK_VOID(vs_ref, FAIL, "VSQueryref");
    status = VSdetach(vsid);
    CHECK_VOID(status, FAIL, "VSdetach");

    /* Attach to vdata NONSPECIAL_VS to write data, but first verify that
        number of data blocks is 0 */
    vsid = VSattach(fid, vs_ref, "w");
    CHECK_VOID(vsid, FAIL, "VSattach");

    n_blocks = VSgetdatainfo(vsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    VERIFY_VOID(n_blocks, 0, "VSgetdatainfo");

    /* Define the fields in the vdata */
    status_n = VSfdefine(vsid, FIELD1_NAME, DFNT_INT32, ORDER_1);
    CHECK_VOID(status_n, FAIL, "VSfdefine");
    status_n = VSfdefine(vsid, FIELD2_NAME, DFNT_INT32, ORDER_2);
    CHECK_VOID(status_n, FAIL, "VSfdefine");
    status_n = VSfdefine(vsid, FIELD3_NAME, DFNT_INT32, ORDER_3);
    CHECK_VOID(status_n, FAIL, "VSfdefine");
    status_n = VSsetfields(vsid, FIELD_NAME_LIST);
    CHECK_VOID(status_n, FAIL, "VSsetfields");

    /*
     * Buffer the data by the record for fully interlaced mode.  Note that the
     * first three elements contain the three values of the first field, the
     * fourth element contains the value of the second field, and the last two
     * elements contain the two values of the third field.
     */
    for (rec_num = 0; rec_num < N_RECORDS; rec_num++) {
        data_buf1[rec_num][0] = 2; /* easier to inspect the binary file using */
        data_buf1[rec_num][1] = 2; /* a simple value */
        data_buf1[rec_num][2] = 2;
        data_buf1[rec_num][3] = 2;
        data_buf1[rec_num][4] = 2;
        data_buf1[rec_num][5] = 2;
        /*  data_buf1[rec_num][0] = 1 + rec_num;
        data_buf1[rec_num][1] = 2 + rec_num;
        data_buf1[rec_num][2] = 3 + rec_num;
        data_buf1[rec_num][3] = 10 + rec_num;
        data_buf1[rec_num][4] = 10;
        data_buf1[rec_num][5] = 65;
 */
    }

    /* Set the block size and the number of blocks */
    status_n = VSsetblocksize(vsid, BLOCK_SIZE);
    CHECK_VOID(status_n, FAIL, "VSsetblocksize");
    status_n = VSsetnumblocks(vsid, NUM_BLOCKS);
    CHECK_VOID(status_n, FAIL, "VSsetnumblocks");

    /* Write the data from data_buf1 to the non special vdata */
    n_records = VSwrite(vsid, (uint8 *)data_buf1, N_RECORDS, FULL_INTERLACE);
    VERIFY_VOID(n_records, N_RECORDS, "VSwrite");

    n_blocks = VSgetdatainfo(vsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    VERIFY_VOID(n_blocks, 1, "VSgetdatainfo");

    n_blocks = VSgetdatainfo(vsid, 0, n_blocks, &offset, &length);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");

    /* Verify offset/length */
    VERIFY_VOID(offset, 456, "VSgetdatainfo offset from NONSPECIAL_VS");
    VERIFY_VOID(length, 120, "VSgetdatainfo length from NONSPECIAL_VS");

    status_n = VSdetach(vsid);
    CHECK_VOID(status_n, FAIL, "VSdetach");

    /* Create and write to another simple vdata, named 'Characters Only', in
        class CONTCLASS_NAME */
    vs_ref = VHstoredata(fid, "Only field", (const uint8 *)data_buf2, N_RECORDS, DFNT_CHAR, "Characters Only",
                         CONTCLASS_NAME);
    CHECK_VOID(vs_ref, FAIL, "VHstoredata");

    /* Attach to vdata 'Characters Only' and get offset and length of its data */
    vsid = VSattach(fid, vs_ref, "r");

    n_blocks = VSgetdatainfo(vsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    VERIFY_VOID(n_blocks, 1, "VSgetdatainfo NONSPECIAL_VS");

    /* Get offset/length */
    n_blocks = VSgetdatainfo(vsid, 0, n_blocks, &offset, &length);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");

    /* Close everything */
    status = VSdetach(vsid);
    CHECK_VOID(status, FAIL, "VSdetach");

    status_n = Vend(fid);
    CHECK_VOID(status_n, FAIL, "Vend");

    status_n = Hclose(fid);
    CHECK_VOID(status_n, FAIL, "Hclose");

    /* Open the file with fopen, read data at the offset obtained and verify
       the values */
    status_n = readnoHDF_char(SIMPLE_FILE, offset, length, data_buf2);
    if (status_n == FAIL)
        fprintf(stderr, "Attempt reading data without HDF4 library failed at line %d\n", __LINE__);
} /* test_simple_vs() */

/****************************************************************************
   Name: test_append_vs() - tests Vdatas with linked-blocks

   Description:
        This routine creates and writes data to an appendable vdata and
        verifies its data information with VSgetdatainfo.  The tests include
        the following:
        - create and write to an appendable vdata
        - create and write to a simple vdata
        - add data to the appendable vdata
        - use VSgetdatainfo to get offsets/lengths of the linked-blocks of data
   BMR - Jul 2010
 ****************************************************************************/
#define APPEND_FILE   "tdatainfo_linkblock.hdf" /* data file */
#define APPENDABLE_VD "Appendable Vdata"
static void
test_append_vs()
{
    int32 fid;                                  /* file ID */
    int32 apvsid;                               /* vdata IDs */
    int32 vs1_ref,                              /* vdata ref# */
        n_records,                              /* number of records written to vdata */
        data_buf0[N_RECORDS][N_VALS_PER_REC_1], /* for "Very Simple Vdata" */
        data_buf1[N_RECORDS][N_VALS_PER_REC_2]; /* for first vdata's data */
    int16            rec_num;                   /* current record number */
    intn             n_blocks;
    t_hdf_datainfo_t vs_info;
    int32            status;   /* Status values from routines */
    intn             status_n; /* Status values from routines */

    /* Open the HDF file. */
    fid = Hopen(APPEND_FILE, DFACC_CREATE, 0);
    CHECK_VOID(fid, FAIL, "Hopen");

    /* Initialize HDF for subsequent vgroup/vdata access. */
    status_n = Vstart(fid);
    CHECK_VOID(status_n, FAIL, "Vstart");

    /* Create the first vdata */
    apvsid = VSattach(fid, -1, "w");
    CHECK_VOID(apvsid, FAIL, "VSattach");

    vs1_ref = VSQueryref(apvsid);
    CHECK_VOID(vs1_ref, FAIL, "VSQueryref:apvsid");

    status = VSdetach(apvsid);
    CHECK_VOID(status, FAIL, "VSdetach");

    apvsid = VSattach(fid, vs1_ref, "w");
    CHECK_VOID(apvsid, FAIL, "VSattach");

    /* Set name and class name of the vdata. */
    status = VSsetname(apvsid, APPENDABLE_VD);
    CHECK_VOID(status, FAIL, "VSsetname");
    status = VSsetclass(apvsid, LINKED_BLOCK);
    CHECK_VOID(status, FAIL, "VSsetclass");

    n_blocks = VSgetdatainfo(apvsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    VERIFY_VOID(n_blocks, 0, "VSgetdatainfo");

    /* Introduce each field's name, data type, and order.  This is the first
      part in defining a field.  */
    status_n = VSfdefine(apvsid, FIELD1_NAME, DFNT_INT32, ORDER_1);
    CHECK_VOID(status_n, FAIL, "VSfdefine");
    status_n = VSfdefine(apvsid, FIELD2_NAME, DFNT_INT32, ORDER_2);
    CHECK_VOID(status_n, FAIL, "VSfdefine");
    status_n = VSfdefine(apvsid, FIELD3_NAME, DFNT_INT32, ORDER_3);
    CHECK_VOID(status_n, FAIL, "VSfdefine");

    /* Finalize the definition of the fields. */
    status_n = VSsetfields(apvsid, FIELD_NAME_LIST);
    CHECK_VOID(status_n, FAIL, "VSsetfields");

    /*
     * Buffer the data by the record for fully interlaced mode.  Note that the
     * first three elements contain the three values of the first field, the
     * fourth element contains the value of the second field, and the last two
     * elements contain the two values of the third field.
     */
    for (rec_num = 0; rec_num < N_RECORDS; rec_num++) {
        data_buf1[rec_num][0] = 5; /* easier to inspect the bin file */
        data_buf1[rec_num][1] = 5;
        data_buf1[rec_num][2] = 5;
        data_buf1[rec_num][3] = 5;
        data_buf1[rec_num][4] = 5;
        data_buf1[rec_num][5] = 5;

        /* data_buf1[rec_num][0] = 1 + rec_num;
       data_buf1[rec_num][1] = 2 + rec_num;
       data_buf1[rec_num][2] = 3 + rec_num;
       data_buf1[rec_num][3] = 10 + rec_num;
       data_buf1[rec_num][4] = 10;
       data_buf1[rec_num][5] = 65;
*/
    }

    /* Set the block size and the number of blocks the first vdata */
    status_n = VSsetblocksize(apvsid, BLOCK_SIZE);
    CHECK_VOID(status_n, FAIL, "VSsetblocksize");
    status_n = VSsetnumblocks(apvsid, NUM_BLOCKS);
    CHECK_VOID(status_n, FAIL, "VSsetnumblocks");

    /* Write the data from data_buf1 to vdata APPENDABLE_VD the first time */
    n_records = VSwrite(apvsid, (uint8 *)data_buf1, N_RECORDS, FULL_INTERLACE);
    VERIFY_VOID(n_records, N_RECORDS, "VSwrite");

    n_blocks = VSgetdatainfo(apvsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");

    /* Allocate space to record the vdata's data info */
    if (alloc_info(&vs_info, n_blocks) == -1)
        exit(1);

    /* Get offset and lengths of the data */
    n_blocks = VSgetdatainfo(apvsid, 0, n_blocks, vs_info.offsets, vs_info.lengths);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    free_info(&vs_info);

    /* Get the reference number of this vdata for later use */
    vs1_ref = VSQueryref(apvsid);
    CHECK_VOID(vs1_ref, FAIL, "VSQueryref");

    /* Make another simple vdata to cause linked-blocks */
    for (rec_num = 0; rec_num < N_RECORDS; rec_num++)
        data_buf0[rec_num][0] = 10 + rec_num;

    /* Create and write to another very simple vdata */
    VHstoredata(fid, "Field 1", (const uint8 *)data_buf0, N_RECORDS, DFNT_INT32,
                "Another One Field One Order", "Very Simple Vdata");

    /* Make up the second batch of data for the appendable vdata */
    for (rec_num = 0; rec_num < N_RECORDS; rec_num++) {
        data_buf1[rec_num][0] = 100 + rec_num;
        data_buf1[rec_num][1] = 200 + rec_num;
        data_buf1[rec_num][2] = 300 + rec_num;
        data_buf1[rec_num][3] = 1000 + rec_num;
        data_buf1[rec_num][4] = 1000;
        data_buf1[rec_num][5] = 6500;
    }
    /* Write the data to vdata APPENDABLE_VD the second time */
    n_records = VSwrite(apvsid, (uint8 *)data_buf1, N_RECORDS, FULL_INTERLACE);
    VERIFY_VOID(n_records, N_RECORDS, "VSwrite");

    /* Detach this vdata and attach to it again, just to make sure meta-data
       is recorded; it may not be necessary but it doesn't hurt */
    status = VSdetach(apvsid);
    CHECK_VOID(status, FAIL, "VSdetach");
    apvsid = VSattach(fid, vs1_ref, "w");
    CHECK_VOID(apvsid, FAIL, "VSattach");

    /* Get the number of data blocks the vdata currently has */
    n_blocks = VSgetdatainfo(apvsid, 0, 0, NULL, NULL);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");
    VERIFY_VOID(n_blocks, 3, "VSgetdatainfo");

    /* Allocate space to record the vdata's data info */
    if (alloc_info(&vs_info, n_blocks) == -1)
        exit(1);

    /* Record various info to be used in verifying data later */
    vs_info.n_values = 30;
    vs_info.numtype  = DFNT_INT32;

    /* Get and verify offsets and lengths of data */
    n_blocks = VSgetdatainfo(apvsid, 0, n_blocks, vs_info.offsets, vs_info.lengths);
    CHECK_VOID(n_blocks, FAIL, "VSgetdatainfo");

    {
        int   ii;
        int32 check_offsets[] = {294, 556, 636};
        int32 check_lengths[] = {120, 80, 40}; /* last chunk is not completely filled */
        for (ii = 0; ii < n_blocks; ii++) {
            VERIFY_VOID(vs_info.offsets[ii], check_offsets[ii], "VSgetdatainfo offset");
            VERIFY_VOID(vs_info.lengths[ii], check_lengths[ii], "VSgetdatainfo length");
        }
    }
    /* Verifying data read without HDF4 library */
    /* NOT YET */

    /* Release memory */
    free_info(&vs_info);

    /* Close everything */
    status = VSdetach(apvsid);
    CHECK_VOID(status, FAIL, "Vdetach");
    status = Vend(fid);
    CHECK_VOID(status, FAIL, "Vend");
    status = Hclose(fid);
    CHECK_VOID(status, FAIL, "Hclose");
} /* test_append_vs */

/*******************************************************************
  Name: readnoHDF_char - utility routine to read and verify character
                        data without HDF4 library

  Description:
        readnoHDF_char opens the file and reads in data at the specified
        offset.  The read data is compared against the original data passed
        by caller.  If any mismatch occurs, an error message will be
        displayed but the process will continue.

  Parameters:
        char *filename	IN: name of the file
        int32 offset	IN: where to start read data
        int32 length	IN: how long to read the data

  Return value:
        SUCCEED/FAIL
  BMR - Jul 2010
********************************************************************/
intn
readnoHDF_char(const char *filename, const int32 offset, const int32 length, const char *orig_buf)
{
    FILE  *fd;          /* file descriptor */
    size_t readlen = 0; /* number of bytes actually read */
    char  *readcbuf;
    intn   ret_value = SUCCEED;

    /* Open the file for reading without SD API */
    fd = fopen(filename, "r");
    if (fd == NULL) {
        fprintf(stderr, "readnoHDF_char: unable to open file %s", filename);
        ret_value = FAIL;
    }

    /* Forward to the position of the first block of data */
    if (fseek(fd, (off_t)offset, SEEK_SET) == -1) {
        fprintf(stderr, "readnoHDF_char: unable to seek offset %d\n", (int)offset);
        ret_value = FAIL;
    }

    /* Allocate buffers for SDS' data */
    readcbuf = (char *)malloc(length * sizeof(char));
    if (readcbuf == NULL) {
        fprintf(stderr, "readnoHDF_char: allocation readcbuf failed\n");
        ret_value = FAIL;
    }

    /* Read in this block of data */
    readlen = fread((void *)readcbuf, 1, length, fd);
    if (readlen > 0) {
        /* Compare data read without HDF4 lib against the original buffer */
        if (strncmp(readcbuf, orig_buf, readlen) != 0)
            fprintf(stderr,
                    "Failure: non-HDF reading got different values than written values\n   >>> written = "
                    "%s\n   >>> read = %s\n",
                    orig_buf, readcbuf);
    }
    free(readcbuf);
    /* Close the file */
    if (fclose(fd) == -1) {
        fprintf(stderr, "readnoHDF_char: unable to close file %s", filename);
        ret_value = FAIL;
    }
    return ret_value;
}

/*******************************************************************
  Name: get_annot_datainfo - utility routine to get datainfo of
        an annotation

  Description:
        get_annot_datainfo gets access to each annotation, then attempts to
        get the offset/length of its data.  If successful, increment the
        data info count and eventually returns that number to caller.  If
        failure occurs, simply return FAIL and all the previous data info
        will be discarded by the caller.

  Parameters:
        int32 an_id		IN: annotation ID
        ann_type annot_type	IN: type of the annotations
        int32 num_anns		IN: number of annotations of the specified type,
                                    currently only 1, but will be adjusted after
                                    the last parameter become arrays of strings
        t_ann_info_t *ann_info	OUT: structure that holds ann data info
        intn ann_info_num	IN: indicates where in ann_info to start
                                    storing info
        char* ann_text		IN: text of the annotation (this will be changed
                                    to array of strings when time permits)

  Return value:
        The number of annotations whose data info is successfully retrieved
        and stored in ann_info or FAIL if failure occurs.
********************************************************************/
intn
get_annot_datainfo(int32 an_id, ann_type annot_type, int32 num_anns, t_ann_info_t *ann_info,
                   intn ann_info_num, char *ann_text)
{
    int32 ann_id, ann_index;
    intn  status_n, ret_value = 0;

    /* Get the annotation. */
    for (ann_index = 0; ann_index < num_anns; ann_index++) {
        /* Get the identifier of the current annotation. */
        ann_id = ANselect(an_id, ann_index, annot_type);
        CHECK(ann_id, FAIL, "ANselect");

        /* Get annotation's data info. */
        status_n = ANgetdatainfo(ann_id, &ann_info[ann_info_num].offset, &ann_info[ann_info_num].length);
        CHECK(status_n, FAIL, "ANgetdatainfo");

        /* Store annotation text for later checking against data read from
           the file without HDF4 library */
        strcpy(ann_info[ann_info_num].anntext, ann_text);

        /* Terminate access to the current annotation. */
        status_n = ANendaccess(ann_id);
        CHECK(status_n, FAIL, "ANendaccess");

        /* Number of annotations whose datainfo is retrieved */
        ret_value++;
    }
    return ret_value;
} /* get_annot_datainfo */

/****************************************************************************
   Name: test_annotation() - tests getting data info of annotations

   Description:
        This routine tests getting data info of file label and description,
        and data label and description.
        - add a file label and a file description
        - create a vgroup then add a data label and a data description to it
        - use the utility routine get_annot_datainfo to record the offset,
          length, and annotation text
        - use utility routine readnoHDF_char to read the annotation text
          without the use of the HDF4 library and verify the correctness of
          the read data

        Todo 2: Should add more annotations so there will be multiple annots
        for an object or file.  get_annot_datainfo needs to be fixed to
        accommodate this.
   BMR - Aug 2010
   NOTE:
        It is near the end of H4 Mapping project and Ruth had said there were
        no annotation for Vgroup and Vdata, so the continuation of these tests
        is not that critical anymore.  For SDS, SDgetanndatainfo handles
        annotations already.  BMR - Jan 2011
 ****************************************************************************/
#define ANNOT_FILE     "tdatainfo_annot.hdf" /* data file */
#define VG_NAME        "AN Vgroup"
#define FILE_LABEL_TXT "General HDF objects"
#define FILE_DESC_TXT  "This is an HDF file that contains general HDF objects"
#define DATA_LABEL_TXT "Common AN Vgroup"
#define DATA_DESC_TXT  "This is a vgroup that is used to test data annotations"
static void
test_annotation()
{
    int32 fid,                           /* file ID */
        an_id,                           /* AN interface ID */
        file_label_id,                   /* file label ID */
        file_desc_id,                    /* file description ID */
        data_label_id,                   /* data label ID */
        data_desc_id,                    /* data description ID */
        vgroup_id;                       /* vgroup ID */
    uint16       vgroup_tag, vgroup_ref; /* vgroup tag/ref */
    t_ann_info_t ann_info[4];            /* temporary storage of annotation info */
    intn         status_n;               /* returned status for functions returning an intn  */
    int32        status;                 /* returned status for functions returning an int32 */

    /* Create the HDF file. */
    fid = Hopen(ANNOT_FILE, DFACC_CREATE, 0);
    CHECK_VOID(fid, FAIL, "Hopen");

    /* Initialize the AN interface. */
    an_id = ANstart(fid);
    CHECK_VOID(an_id, FAIL, "ANstart");

    /* Create and write a file label. */
    file_label_id = ANcreatef(an_id, AN_FILE_LABEL);
    CHECK_VOID(file_label_id, FAIL, "ANcreatef");
    status = ANwriteann(file_label_id, FILE_LABEL_TXT, strlen(FILE_LABEL_TXT));
    CHECK_VOID(status, FAIL, "ANwriteann");

    /* Create and write a file description. */
    file_desc_id = ANcreatef(an_id, AN_FILE_DESC);
    CHECK_VOID(file_desc_id, FAIL, "ANcreatef");
    status = ANwriteann(file_desc_id, FILE_DESC_TXT, strlen(FILE_DESC_TXT));
    CHECK_VOID(status, FAIL, "ANwriteann");

    /* Create a vgroup to add annotation to it. */
    status_n = Vstart(fid);
    CHECK_VOID(status_n, FAIL, "Vstart");
    vgroup_id = Vattach(fid, -1, "w");
    CHECK_VOID(vgroup_id, FAIL, "Vattach");
    status = Vsetname(vgroup_id, VG_NAME);
    CHECK_VOID(status, FAIL, "Vsetname");

    /* Get the tag and ref number of the vgroup for ANcreate. */
    vgroup_tag = (uint16)VQuerytag(vgroup_id);
    CHECK_VOID(vgroup_tag, 0, "VQuerytag");
    vgroup_ref = (uint16)VQueryref(vgroup_id);
    CHECK_VOID(vgroup_ref, 0, "VQueryref");

    /* Add a data label to the vgroup. */
    data_label_id = ANcreate(an_id, vgroup_tag, vgroup_ref, AN_DATA_LABEL);
    CHECK_VOID(data_label_id, FAIL, "ANcreate");
    status = ANwriteann(data_label_id, DATA_LABEL_TXT, strlen(DATA_LABEL_TXT));
    CHECK_VOID(status, FAIL, "ANwriteann");

    /* Add a data description to the vgroup. */
    data_desc_id = ANcreate(an_id, vgroup_tag, vgroup_ref, AN_DATA_DESC);
    CHECK_VOID(data_desc_id, FAIL, "ANcreate");
    status = ANwriteann(data_desc_id, DATA_DESC_TXT, strlen(DATA_DESC_TXT));
    CHECK_VOID(status, FAIL, "ANwriteann");

    /* Terminate access to each annotation. */
    status_n = ANendaccess(file_label_id);
    CHECK_VOID(status_n, FAIL, "ANendaccess");
    status_n = ANendaccess(file_desc_id);
    CHECK_VOID(status_n, FAIL, "ANendaccess");
    status_n = ANendaccess(data_label_id);
    CHECK_VOID(status_n, FAIL, "ANendaccess");
    status_n = ANendaccess(data_desc_id);
    CHECK_VOID(status_n, FAIL, "ANendaccess");

    /* Terminate access to the vgroup and to the V interface. */
    status   = Vdetach(vgroup_id);
    status_n = Vend(fid);

    /* Terminate access to the AN interface and close the HDF file. */
    status = ANend(an_id);
    CHECK_VOID(status, FAIL, "ANend");
    status_n = Hclose(fid);
    CHECK_VOID(status_n, FAIL, "Hclose");

    /* Open the file and read in location/size of all annotations */

    {
        int32 ann_index,   /* annotation index */
            n_file_labels, /* numbers of file labels */
            n_file_descs,  /* numbers of file descs */
            n_data_labels, /* numbers of data labels */
            n_data_descs;  /* numbers of data descs */
        intn num_anns = 0, ann_info_num = 0;

        /* Open the file. */
        fid = Hopen(ANNOT_FILE, DFACC_RDONLY, 0);
        CHECK_VOID(fid, FAIL, "Hopen");

        /* Initialize the AN interface. */
        an_id = ANstart(fid);
        CHECK_VOID(an_id, FAIL, "ANstart");

        /* Get the number of data/file labels/descriptions */
        status_n = ANfileinfo(an_id, &n_file_labels, &n_file_descs, &n_data_labels, &n_data_descs);
        CHECK_VOID(status_n, FAIL, "ANfileinfo");
        VERIFY_VOID(n_file_labels, 1, "ANfileinfo");
        VERIFY_VOID(n_file_descs, 1, "ANfileinfo");
        VERIFY_VOID(n_data_labels, 1, "ANfileinfo");
        VERIFY_VOID(n_data_descs, 1, "ANfileinfo");

        /* Get access to each annotation then call ANgetdatainfo to retrieve
           the offset/length of the annotation data */

        /* Explanation of some parameters to get_annot_datainfo:
           3rd parameter - number of annotations of the specified type,
           currently only 1, but will adjust the last parameter to have arrays
           of character strings when have time.
           4th parameter - ann_info_num indicates where in ann_info to start
           storing info */

        /* AN_DATA_LABEL */
        num_anns = get_annot_datainfo(an_id, AN_DATA_LABEL, 1, ann_info, ann_info_num, DATA_LABEL_TXT);
        CHECK_VOID(num_anns, FAIL, "get_annot_datainfo");
        VERIFY_VOID(num_anns, 1, "get_annot_datainfo");
        ann_info_num = ann_info_num + num_anns;

        /* AN_DATA_DESC */
        num_anns = get_annot_datainfo(an_id, AN_DATA_DESC, 1, ann_info, ann_info_num, DATA_DESC_TXT);
        CHECK_VOID(num_anns, FAIL, "get_annot_datainfo");
        VERIFY_VOID(num_anns, 1, "get_annot_datainfo");
        ann_info_num = ann_info_num + num_anns;

        /* AN_FILE_LABEL */
        num_anns = get_annot_datainfo(an_id, AN_FILE_LABEL, 1, ann_info, ann_info_num, FILE_LABEL_TXT);
        CHECK_VOID(num_anns, FAIL, "get_annot_datainfo");
        VERIFY_VOID(num_anns, 1, "get_annot_datainfo");
        ann_info_num = ann_info_num + num_anns;

        /* AN_FILE_DESC */
        num_anns = get_annot_datainfo(an_id, AN_FILE_DESC, 1, ann_info, ann_info_num, FILE_DESC_TXT);
        CHECK_VOID(num_anns, FAIL, "get_annot_datainfo");
        VERIFY_VOID(num_anns, 1, "get_annot_datainfo");
        ann_info_num = ann_info_num + num_anns;

        /* Terminate access to the AN interface and close the HDF file. */
        status = ANend(an_id);
        CHECK_VOID(status, FAIL, "ANend");
        status_n = Hclose(fid);
        CHECK_VOID(status_n, FAIL, "Hclose");

        /* calling readnoHDF_char to verify data without the use of HDF lib */

        for (ann_index = 0; ann_index < ann_info_num; ann_index++) {
            /* Open the file with fopen, read data at the offset obtained and
               verify the values */
            status_n = readnoHDF_char(ANNOT_FILE, ann_info[ann_index].offset, ann_info[ann_index].length,
                                      ann_info[ann_index].anntext);
            if (status_n == FAIL)
                fprintf(stderr, "Attempt reading data without HDF4 library failed at line %d\n", __LINE__);
        }
    }
} /* test_annotation */

/****************************************************************************
   Name: test_oneblock_ri() - tests non-linked-block images

   Description:
        This routine creates and writes data to images and verifies
        some data and data information with GRgetdatainfo.  The tests include
        the following images:
        - a simple, non-compressed image
        - three images with RLE, Skipping-Huffman, and Deflate compression
        Only the non-compressed image's values are verified against the original
        buffer.  The other three were verified by debugging, additional
        decompression code needed for further verification (Todo 2)

   Note: Incomplete, waiting for schema design
   BMR - Aug 2010
 ****************************************************************************/
#define IMAGE_FILE       "tdatainfo_images.hdf" /* data file */
#define NONCOMP_IMAGE    "Image with No Compression"
#define RLE_IMAGE        "Image with RLE Compression"
#define DEFLATE_IMAGE    "Image with Deflate Compression"
#define SKPHUFF_IMAGE    "Image with Skphuff Compression"
#define JPEG_IMAGE       "Image with JPEG Compression"
#define SKPHUFF_SKIPSIZE 28
#define DEFLATE_LEVEL    7
#define WIDTH            5
#define LENGTH           5
#define N_IMAGES         4

/* Convenient function to create and write to an image, used by
   test_oneblock_ri */
static intn
make_comp_image(int32 grid, char *img_name,
                char       start_char, /* first value in the image, for variety of data */
                int32      comp_type,  /* compression method */
                comp_info *cinfo)      /* compression parameters */
{
    int32 riid;                      /* raster image ID */
    int32 dims[2] = {WIDTH, LENGTH}; /* dimensions for the image */
    char  image0[WIDTH][LENGTH];     /* image data */
    int32 start[2];                  /* start of image data to grab */
    int32 stride[2];                 /* stride of image data to grab */
    intn  ii, jj;                    /* indices */
    intn  status;                    /* generic return value */
    intn  ret_value = SUCCEED;

    /* Initialize data we are going to write out, each image created by this
       convenient function will use the same data pattern with the first value
       given by the caller  */
    for (ii = 0; ii < WIDTH; ii++)
        for (jj = 0; jj < LENGTH; jj++)
            image0[ii][jj] = start_char + jj;

    /* Create the image with 1 component, type char, pixel interlace, and
       dimension WIDTHxLENGTH */
    riid = GRcreate(grid, img_name, 1, DFNT_CHAR, MFGR_INTERLACE_PIXEL, dims);
    CHECK(riid, FAIL, "GRcreate");

    /* Set compression as instructed */
    if (comp_type != COMP_CODE_NONE) {
        status = GRsetcompress(riid, comp_type, cinfo);
        CHECK(status, FAIL, "GRsetcompress");
    }

    /* Write the entire image data out */
    start[0] = start[1] = 0;
    stride[0] = stride[1] = 1;
    status                = GRwriteimage(riid, start, stride, dims, image0);
    CHECK(status, FAIL, "GRreadimage");

    /* Close the first image */
    status = GRendaccess(riid);
    CHECK(status, FAIL, "GRendaccess");

    return ret_value;
}

static void
test_oneblock_ri()
{
    int32 fid, grid,          /* file ID and GR interface ID */
        riid;                 /* raster image ID */
    int32     offset, length; /* offset/length buffers for single block of data */
    intn      status;         /* status returned from routines */
    intn      ii;             /* indices */
    int32     n_images, n_fattrs;
    comp_info cinfo; /* Compression parameters - union */
    /* offsets/lengths to be used to verify offsets/lengths returned by
       GRgetdatainfo - confirmed by the command "od" on the hdf file */
    static int32 image_data_offsets[N_IMAGES] = {309, 363, 426, 486};
    static int32 image_data_lengths[N_IMAGES] = {25, 26, 29, 16};

    /****************************************************************
      Create a file in GR interface then create and write several
      images with and without compression.
    ****************************************************************/

    /* Create the HDF file and initialize the interface. */
    fid = Hopen(IMAGE_FILE, DFACC_CREATE, 0);
    CHECK_VOID(fid, FAIL, "Hopen");

    grid = GRstart(fid);
    CHECK_VOID(grid, FAIL, "GRstart");

    /* Create and write the non-compressed image to this file */
    status = make_comp_image(grid, NONCOMP_IMAGE, 'n', COMP_CODE_NONE, &cinfo);

    /* Create and write 3 more images: RLE, Deflate, and Skipping Huffman */

    /* No compression info for the RLE image */
    memset(&cinfo, 0, sizeof(cinfo));

    /* Create and write the RLE compressed image to this file, starting the
       data values with the letter 'r' */
    status = make_comp_image(grid, RLE_IMAGE, 'r', COMP_CODE_RLE, &cinfo);

    /* Set the compression info for the image with Skipping Huffman method */
    memset(&cinfo, 0, sizeof(cinfo));
    cinfo.skphuff.skp_size = SKPHUFF_SKIPSIZE;

    /* Create and write the Skipping Huffman compressed image to this file,
       starting the data values with the letter 's' */
    status = make_comp_image(grid, SKPHUFF_IMAGE, 's', COMP_CODE_SKPHUFF, &cinfo);

    /* Set the compression info for the image with Deflate method */
    memset(&cinfo, 0, sizeof(cinfo));
    cinfo.deflate.level = DEFLATE_LEVEL;

    /* Create and write the Deflate compressed image to this file, starting the
       data values with the letter 'd' */
    status = make_comp_image(grid, DEFLATE_IMAGE, 'd', COMP_CODE_DEFLATE, &cinfo);

    /* Set the compression method for the image with JPEG method */
    memset(&cinfo, 0, sizeof(cinfo));
    cinfo.jpeg.quality        = 100;
    cinfo.jpeg.force_baseline = 1;

    /* Create and write the JPEG compressed image to this file, starting the
       data values with the letter 'j' - more work to be done for JPEG */
    /* status = make_comp_image(grid, JPEG_IMAGE, 'j', COMP_CODE_JPEG, &cinfo);
     */

    /* Terminate access to the GR interface and close the file */
    status = GRend(grid);
    CHECK_VOID(status, FAIL, "GRend");
    status = Hclose(fid);
    CHECK_VOID(status, FAIL, "Hclose");

    /****************************************************************
      Re-open the file to read the images and their data information
    ****************************************************************/

    /* Re-open the file and initialize the GR interface */
    fid = Hopen(IMAGE_FILE, DFACC_RDONLY, 0);
    CHECK_VOID(fid, FAIL, "Hopen");
    grid = GRstart(fid);
    CHECK_VOID(grid, FAIL, "GRstart");

    /* Get the number of images in the file */
    status = GRfileinfo(grid, &n_images, &n_fattrs);
    CHECK_VOID(status, FAIL, "GRfileinfo");
    VERIFY_VOID(n_images, N_IMAGES, "GRfileinfo");

    /* Open each image then get and verify its data information.  Note that
        currently, the offsets and lengths are obtained from debugging
        and the command od on the file */
    for (ii = 0; ii < n_images; ii++) {
        riid = GRselect(grid, ii);
        CHECK_VOID(riid, FAIL, "GRselect");

        status = GRgetdatainfo(riid, 0, 1, &offset, &length);
        CHECK_VOID(status, FAIL, "GRgetdatainfo");
        VERIFY_VOID(offset, image_data_offsets[ii], "GRgetdatainfo");
        VERIFY_VOID(length, image_data_lengths[ii], "GRgetdatainfo");

        /* Only verify data of the first image, which has non-compressed data. */
        if (ii == 0) {
            intn jj, kk;
            char buffer[WIDTH][LENGTH], check_image[WIDTH * LENGTH];
            for (kk = 0; kk < WIDTH; kk++)
                for (jj = 0; jj < LENGTH; jj++)
                    buffer[kk][jj] = 'n' + jj;

            /* Work around to pass check_image into readnoHDF_char w/o warning*/
            memcpy(check_image, buffer, WIDTH * LENGTH);

            /* Open the file with fopen, read data at the offset obtained and verify
               the values */
            status = readnoHDF_char(IMAGE_FILE, offset, length, check_image);
            if (status == FAIL)
                fprintf(stderr, "Attempt reading data without HDF4 library failed at line %d\n", __LINE__);
        }

        /* Close the image */
        status = GRendaccess(riid);
        CHECK_VOID(status, FAIL, "GRendaccess");
    } /* for n_images */

    /* Terminate access to the GR interface and close the file */
    status = GRend(grid);
    CHECK_VOID(status, FAIL, "GRend");
    status = Hclose(fid);
    CHECK_VOID(status, FAIL, "Hclose");
} /* end test_oneblock_ri */

#define IMAGE_DF_FILE "tdatainfo_dfri.hdf" /* data file for DFR APIs */
#define N_DF_IMAGES                                                                                          \
    2 /* number of DF images in the file, 1 RI8 &                                                            \
         1 RI24 */
static void
test_dfr8_24()
{
    int32 fid, grid,      /* file ID and GR interface ID */
        riid;             /* raster image ID */
    int32 offset, length; /* offset/length buffers for single block of data */
    intn  status;         /* status returned from routines */
    intn  ii, jj;         /* indices */
    int32 n_images, n_fattrs;
    char  buf[WIDTH][LENGTH][3];

    /* offsets/lengths to be used to verify offsets/lengths returned by
       GRgetdatainfo - confirmed by the command "od" on the hdf file */
    static int32 image_data_offsets[N_IMAGES] = {294, 1132};
    static int32 image_data_lengths[N_IMAGES] = {30, 75};

    /* Initialize the 8-bit image array */
    static uint8 raster_data[WIDTH][LENGTH] = {
        {1, 2, 3, 4, 5}, {5, 4, 3, 2, 1}, {1, 2, 3, 4, 5}, {5, 4, 3, 2, 1}, {6, 4, 2, 0, 2}};

    /* Write the 8-bit raster image to file */
    status = DFR8putimage(IMAGE_DF_FILE, raster_data, WIDTH, LENGTH, COMP_RLE);

    /* Initialize the 24-bit image array */
    for (ii = 0; ii < WIDTH; ii++)
        for (jj = 0; jj < LENGTH; jj++) {
            buf[ii][jj][0] = buf[ii][jj][1] = buf[ii][jj][2] = (char)(ii + jj);
        }

    /* Set interlace for the 24-bit RI */
    status = DF24setil(DFIL_PIXEL);

    /* Make sure that no compression is being used - the variable Grcompr is
       global in dfgr.c so its value is inherited from other tests in the lib
       and causes this image to be compressed with JPEG unintentionally.  We
       want to be able to see the data to verify it with "od" */
    status = DF24setcompress(COMP_NONE, NULL);

    /* Write the 24-bit raster image to file */
    status = DF24addimage(IMAGE_DF_FILE, &(buf[0][0][0]), WIDTH, LENGTH);

    /****************************************************************
      Re-open the file to read the images and their data information
     ****************************************************************/
    /* Re-open the file and initialize the GR interface */
    fid = Hopen(IMAGE_DF_FILE, DFACC_RDONLY, 0);
    CHECK_VOID(fid, FAIL, "Hopen");
    grid = GRstart(fid);
    CHECK_VOID(grid, FAIL, "GRstart");

    /* Get the number of images in the file */
    status = GRfileinfo(grid, &n_images, &n_fattrs);
    CHECK_VOID(status, FAIL, "GRfileinfo");
    VERIFY_VOID(n_images, N_DF_IMAGES, "GRfileinfo");

    /* Open each image then get and verify its data information.  Note that
        currently, the offsets and lengths are obtained from debugging
        and the command od on the file */
    for (ii = 0; ii < n_images; ii++) {
        int info_count = FAIL;

        riid = GRselect(grid, ii);
        CHECK_VOID(riid, FAIL, "GRselect");

        /* Get the number of data blocks and verify; should be 1 */
        info_count = GRgetdatainfo(riid, 0, 0, NULL, NULL);
        CHECK_VOID(info_count, FAIL, "GRgetdatainfo");
        VERIFY_VOID(info_count, 1, "GRgetdatainfo");

        /* Get offset/length of the image and verify with pre-determined
           values */
        info_count = GRgetdatainfo(riid, 0, info_count, &offset, &length);
        CHECK_VOID(info_count, FAIL, "GRgetdatainfo");
        VERIFY_VOID(offset, image_data_offsets[ii], "GRgetdatainfo");
        VERIFY_VOID(length, image_data_lengths[ii], "GRgetdatainfo");

        /* Close the image */
        status = GRendaccess(riid);
        CHECK_VOID(status, FAIL, "GRendaccess");
    } /* for n_images */

    /* Terminate access to the GR interface and close the file */
    status = GRend(grid);
    CHECK_VOID(status, FAIL, "GRend");
    status = Hclose(fid);
    CHECK_VOID(status, FAIL, "Hclose");
} /* test_dfr8_24 */

/*************************************************************************
 test_getpalinfo() - tests GRgetpalinfo
 Need documentation
**************************************************************************/
#define IMAGE_DFPAL_FILE "tdatainfo_pal.hdf"
#define IMAGE_WITH_PAL   "GR Image with Palette"
#define IMAGE2_WITH_PAL  "Second GR Image w/pal"
#define ANO_IMAGE_NAME   "ANO_IMAGE_NAME"
#define LASTIMAGE_NOPAL  "Last GR Image: no pal"
#define N_COMPS_IMG      2   /* number of image components */
#define N_ENTRIES        256 /* number of entries in the palette */
#define N_COMPS_PAL      3   /* number of palette's components */

static void
test_getpalinfo()
{
    int32 fid, grid,                             /* file ID and GR interface ID */
        riid, palid,                             /* raster image ID and palette ID */
        interlace_mode, start[2],                /* where to start to write for each dimension  */
        edges[2],                                /* specifies how long to write for each dimension */
        dim_sizes[2];                            /* sizes of the two dimensions of the image array */
    uint8 image_buf[WIDTH][LENGTH][N_COMPS_IMG]; /* data of raster image */
    uint8 palette_buf1[N_ENTRIES][N_COMPS_PAL];  /* for LUT mostly */
    uint8 palette_buf2[N_ENTRIES][N_COMPS_PAL];
    uint8 paletteA[N_ENTRIES * N_COMPS_PAL] = {0}; /* for IP8 mostly */
    uint8 paletteB[N_ENTRIES * N_COMPS_PAL] = {0};
    uint8 paletteD[N_ENTRIES * N_COMPS_PAL] = {0};
    intn  n_pals = 0; /* number of palettes, returned by DFPnpals and GRgetpalinfo */

    hdf_ddinfo_t *palinfo_array = NULL; /* list of palette DDs */
    uint8        *inbuf;                /* palette data read back in */
    intn          ii, jj;               /* indices */
    intn          status;               /* status returned from routines */

    /* Initialize the 8-bit image array */
    static uint8 raster_data[WIDTH][LENGTH] = {
        {1, 2, 3, 4, 5}, {5, 4, 3, 2, 1}, {1, 2, 3, 4, 5}, {5, 4, 3, 2, 1}, {6, 4, 2, 0, 2}};

    /* Palettes are added in the following means and order:
        paletteA (DFPputpal)
        paletteB (DFPputpal)
        paletteA (DFR8setpalette/DFR8addimage)
        palette_buf1 (GRwritelut) for image named IMAGE_WITH_PAL
        palette_buf2 (GRwritelut) for image named IMAGE2_WITH_PAL
        paletteB (DFR8setpalette/DFR8addimage)
        paletteD (DFPputpal)
        paletteB (DFPputpal)
        paletteD (DFPputpal)
        palette_buf2 (GRwritelut) for image named IMAGE2_WITH_PAL
        paletteD (DFPputpal)
    */
    /* Add two palettes with DFP API. */
    status = DFPputpal(IMAGE_DFPAL_FILE, paletteA, 0, "w");
    CHECK_VOID(status, FAIL, "DFPputpal");

    status = DFPputpal(IMAGE_DFPAL_FILE, paletteB, 0, "a");
    CHECK_VOID(status, FAIL, "DFPputpal");

    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 2, "DFPputpal"); /* 2 palettes from 2 DFPputpal's */

    /* Specify palette to be used with subsequent 8-bit images */
    status = DFR8setpalette(paletteA);
    CHECK_VOID(status, FAIL, "DFR8setpalette");

    /* Write an 8-bit raster image to the file */
    status = DFR8addimage(IMAGE_DFPAL_FILE, raster_data, WIDTH, LENGTH, COMP_RLE);
    CHECK_VOID(status, FAIL, "DFR8addimage");

    /* Get the number of palettes using DFP API */
    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 3, "DFPputpal");
    /* 3 palettes: 2 DFPputpal's + DFR8setpalette/DFR8addimage combo */

    /* Write another 8-bit raster image to file, without calling another
       DFR8setpalette, that means this image is using the same palette as the
       previous image.  This is when only 201 is created */
    status = DFR8addimage(IMAGE_DFPAL_FILE, raster_data, WIDTH, LENGTH, COMP_RLE);
    CHECK_VOID(status, FAIL, "DFR8addimage");

    /* Thus, the number of palettes returned by DFPnpals should be the same as
       from the last call to DFPnpals */
    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 3, "DFPputpal");

    /****************************************************************
        Re-open the file in GR interface, add a few images with
        palettes, then test GRgetpalinfo on the palettes
     ****************************************************************/

    /* Re-open the file and initialize the GR interface */
    fid = Hopen(IMAGE_DFPAL_FILE, DFACC_RDWR, 0);
    CHECK_VOID(fid, FAIL, "Hopen");
    grid = GRstart(fid);
    CHECK_VOID(grid, FAIL, "GRstart");

    /* Define the dimensions and interlace mode of the image */
    dim_sizes[0]   = LENGTH;
    dim_sizes[1]   = WIDTH;
    interlace_mode = MFGR_INTERLACE_PIXEL;

    /* Create an image named IMAGE_WITH_PAL */
    riid = GRcreate(grid, IMAGE_WITH_PAL, N_COMPS_IMG, DFNT_UINT8, interlace_mode, dim_sizes);

    /* Fill the image data buffer with values */
    for (ii = 0; ii < WIDTH; ii++) {
        for (jj = 0; jj < LENGTH; jj++) {
            image_buf[ii][jj][0] = (ii + jj) + 1;
            image_buf[ii][jj][1] = (ii + jj) + 2;
        }
    }

    /* Define the size of the data to be written */
    start[0] = start[1] = 0;
    edges[0]            = WIDTH;
    edges[1]            = LENGTH;

    /* Write the data in the buffer into the image array */
    status = GRwriteimage(riid, start, NULL, edges, (void *)image_buf);

    /* Initialize the palette data */
    for (ii = 0; ii < N_ENTRIES; ii++) {
        palette_buf1[ii][0] = ii;
        palette_buf1[ii][1] = 0;
        palette_buf1[ii][2] = 8;
    }

    /* Get the identifier of the palette attached to the image IMAGE_WITH_PAL */
    palid = GRgetlutid(riid, 0);

    /* Write data to the palette. */
    status = GRwritelut(palid, N_COMPS_PAL, DFNT_UINT8, interlace_mode, N_ENTRIES, (void *)palette_buf1);

    /* DFPnpals now sees another palette */
    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 4, "DFPputpal");

    /* Terminate access to the first image */
    status = GRendaccess(riid);

    /* Create another image named IMAGE2_WITH_PAL */
    riid = GRcreate(grid, IMAGE2_WITH_PAL, N_COMPS_IMG, DFNT_UINT8, interlace_mode, dim_sizes);

    /* Write the data in the buffer into the image array */
    status = GRwriteimage(riid, start, NULL, edges, (void *)image_buf);

    /* Get the id of the palette attached to the image IMAGE2_WITH_PAL */
    palid = GRgetlutid(riid, 0);

    /* Initialize the palette for second image */
    for (ii = 0; ii < N_ENTRIES; ii++) {
        palette_buf2[ii][0] = 2;
        palette_buf2[ii][1] = 4;
        palette_buf2[ii][2] = 8;
    }

    /* Write data to the palette */
    status = GRwritelut(palid, N_COMPS_PAL, DFNT_UINT8, interlace_mode, N_ENTRIES, (void *)palette_buf2);

    /* DFPnpals now sees another palette */
    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 5, "DFPputpal");

    /* Terminate access to this image */
    status = GRendaccess(riid);
    CHECK_VOID(status, FAIL, "GRendaccess");

    /* Create another image named LASTIMAGE_NOPAL */
    riid = GRcreate(grid, LASTIMAGE_NOPAL, N_COMPS_IMG, DFNT_UINT8, interlace_mode, dim_sizes);
    CHECK_VOID(riid, FAIL, "GRcreate");

    /* Write the data in the buffer into the image array */
    status = GRwriteimage(riid, start, NULL, edges, (void *)image_buf);
    CHECK_VOID(status, FAIL, "GRwriteimage");

    /* Terminate access to the image */
    status = GRendaccess(riid);
    CHECK_VOID(status, FAIL, "GRendaccess");

    status = DFR8setpalette(paletteB);
    CHECK_VOID(status, FAIL, "DFR8setpalette");

    /* Write another 8-bit raster image to file */
    status = DFR8addimage(IMAGE_DFPAL_FILE, raster_data, WIDTH, LENGTH, COMP_RLE);
    CHECK_VOID(status, FAIL, "DFR8addimage");

    /* DFR8setpalette/DFR8addimage just added another palette, so DFPnpals now
       returns 6 */
    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 6, "DFPputpal");

    status = DFPputpal(IMAGE_DFPAL_FILE, paletteD, 0, "a");
    CHECK_VOID(status, FAIL, "DFPputpal");

    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 7, "DFPnpals");

    status = DFPputpal(IMAGE_DFPAL_FILE, paletteB, 0, "a");
    CHECK_VOID(status, FAIL, "DFPputpal");

    status = DFPputpal(IMAGE_DFPAL_FILE, paletteD, 0, "a");
    CHECK_VOID(status, FAIL, "DFPputpal");

    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 9, "DFPputpal");

    /* Create another image named ANO_IMAGE_NAME. */
    riid = GRcreate(grid, ANO_IMAGE_NAME, N_COMPS_IMG, DFNT_UINT8, interlace_mode, dim_sizes);
    CHECK_VOID(riid, FAIL, "GRcreate");

    /* Write the data in the buffer into the image array. */
    status = GRwriteimage(riid, start, NULL, edges, (void *)image_buf);
    CHECK_VOID(status, FAIL, "GRwriteimage");

    /* Get the identifier of the palette attached to the image ANO_IMAGE_NAME */
    palid = GRgetlutid(riid, 0);
    CHECK_VOID(palid, FAIL, "GRgetlutid");

    /* Write data to the palette. */
    status = GRwritelut(palid, N_COMPS_PAL, DFNT_UINT8, interlace_mode, N_ENTRIES, (void *)palette_buf2);

    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 10, "DFPputpal");

    status = GRendaccess(riid);

    status = DFPputpal(IMAGE_DFPAL_FILE, paletteD, 0, "a");
    CHECK_VOID(status, FAIL, "DFPputpal");

    n_pals = DFPnpals(IMAGE_DFPAL_FILE);
    CHECK_VOID(n_pals, FAIL, "DFPnpals");
    VERIFY_VOID(n_pals, 11, "DFPputpal");

    /* Assuming that this file has been written exactly in this manner, this
       is what the palette DDs would look like at this point:
        tag    ref    offset  length
        201    1      294       768
        301    1      294       768
        201    2      1062      768
        301    2      1062      768
        301    3      1860      768
        201    3      1860      768
        201    4      1860      768
        301    4      2973      768 <- cannot be read by DFPgetpal
        301    5      3806      768 <- cannot be read by DFPgetpal
        301    8      4669      768
        201    8      4669      768
        201    5      5449      768
        201    6      6217      768
        301    6      6217      768
        201    7      7183      768
        301    7      7183      768
        301    9      8016      768 <- cannot be read by DFPgetpal
        201    9      8784      768
 */

    /* Read some palettes */
    {

        /* Call GRgetpalinfo the first time, passing in NULL for the palette array,
           to get the number of palettes in the file */
        n_pals = 0;
        n_pals = GRgetpalinfo(grid, 0, NULL);
        CHECK_VOID(n_pals, FAIL, "GRgetpalinfo");

        palinfo_array = (hdf_ddinfo_t *)malloc(n_pals * sizeof(hdf_ddinfo_t));
        CHECK_ALLOC(palinfo_array, "palinfo_array", "test_getpalinfo");

        n_pals = GRgetpalinfo(grid, n_pals, palinfo_array);
        CHECK_VOID(n_pals, FAIL, "GRgetpalinfo");

        /* Read and verify data of the first palette which is pointed to by both
           data identifiers 201/ref and 301/ref */
        /* inbuf = (uint8 *) malloc(palinfo_array[0].length * sizeof(uint8));
         */
        inbuf = (uint8 *)malloc(palinfo_array[0].length);
        CHECK_ALLOC(inbuf, "inbuf", "test_getpalinfo");
        status = Hgetelement(fid, palinfo_array[0].tag, palinfo_array[0].ref, inbuf);
        CHECK_VOID(status, FAIL, "Hgetelement");

        if (memcmp(inbuf, paletteA, palinfo_array[0].length) != 0)
            fprintf(stderr,
                    "palette data pointed by tag/ref = %d/%d at offset/length = %d/%d differs from written\n",
                    palinfo_array[0].tag, palinfo_array[0].ref, palinfo_array[0].offset,
                    palinfo_array[0].length);
        free(inbuf);

        /* Read and verify data of the palette pointed to by 301/4.  This is the
           data element that was not revealed by DFPgetpal because the tag/ref pair
           201/4 is associated with a different offset */

        /* inbuf = (uint8 *) malloc(palinfo_array[7].length * sizeof(uint8));
         */
        inbuf = (uint8 *)malloc(palinfo_array[7].length);
        CHECK_ALLOC(inbuf, "inbuf", "test_getpalinfo");
        status = Hgetelement(fid, palinfo_array[7].tag, palinfo_array[7].ref, inbuf);
        CHECK_VOID(status, FAIL, "Hgetelement");

        if (memcmp(inbuf, palette_buf1, palinfo_array[7].length) != 0)
            fprintf(stderr,
                    "palette data pointed by tag/ref = %d/%d at offset/length = %d/%d differs from written\n",
                    palinfo_array[7].tag, palinfo_array[7].ref, palinfo_array[7].offset,
                    palinfo_array[7].length);
        free(inbuf);

        free(palinfo_array);
    }

    /* Terminate access to the GR interface and close the file */
    status = GRend(grid);
    CHECK_VOID(status, FAIL, "GRend");
    status = Hclose(fid);
    CHECK_VOID(status, FAIL, "Hclose");

} /* test_getpalinfo */

/****************************************************************************
   Name: test_getntinfo() - tests getting number type's information

   Description:
        This routine simply calls Hgetntinfo with various types and verifies
        the information retrieved.
   BMR - Aug 2010
 ****************************************************************************/
static void
test_getntinfo()
{
    hdf_ntinfo_t nt_info;
    intn         status = SUCCEED;

    status = Hgetntinfo(DFNT_UINT8, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_UINT8");
    VERIFY_CHAR_VOID(nt_info.type_name, "uint8", "Hgetntinfo DFNT_UINT8");
    VERIFY_CHAR_VOID(nt_info.byte_order, "bigEndian", "Hgetntinfo DFNT_UINT8");

    status = Hgetntinfo(DFNT_CHAR16, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_CHAR16");
    VERIFY_CHAR_VOID(nt_info.type_name, "char16", "Hgetntinfo DFNT_CHAR16");
    VERIFY_CHAR_VOID(nt_info.byte_order, "bigEndian", "Hgetntinfo DFNT_CHAR16");

    /* Native */
    status = Hgetntinfo(DFNT_NFLOAT32, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_NFLOAT32");
    VERIFY_CHAR_VOID(nt_info.type_name, "float32", "Hgetntinfo DFNT_NFLOAT32");
    VERIFY_CHAR_VOID(nt_info.byte_order, "bigEndian", "Hgetntinfo DFNT_NFLOAT32");

    /* Little endian */
    status = Hgetntinfo(DFNT_LFLOAT32, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_LFLOAT32");
    VERIFY_CHAR_VOID(nt_info.type_name, "float32", "Hgetntinfo DFNT_LFLOAT32");
    VERIFY_CHAR_VOID(nt_info.byte_order, "littleEndian", "Hgetntinfo DFNT_LFLOAT32");

    /* Little endian backward compatible */
    status = Hgetntinfo(DFNT_LCHAR, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_LCHAR");
    VERIFY_CHAR_VOID(nt_info.type_name, "char8", "Hgetntinfo DFNT_LCHAR");
    VERIFY_CHAR_VOID(nt_info.byte_order, "littleEndian", "Hgetntinfo DFNT_LCHAR");

    /* Backward compatible */
    status = Hgetntinfo(DFNT_DOUBLE, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_DOUBLE");
    VERIFY_CHAR_VOID(nt_info.type_name, "float64", "Hgetntinfo DFNT_DOUBLE");
    VERIFY_CHAR_VOID(nt_info.byte_order, "bigEndian", "Hgetntinfo DFNT_DOUBLE");

    /* Native backward compatible */
    status = Hgetntinfo(DFNT_NUCHAR, &nt_info);
    CHECK_VOID(status, FAIL, "Hgetntinfo DFNT_NUCHAR");
    VERIFY_CHAR_VOID(nt_info.type_name, "uchar8", "Hgetntinfo DFNT_NUCHAR");
    VERIFY_CHAR_VOID(nt_info.byte_order, "bigEndian", "Hgetntinfo DFNT_NUCHAR");
} /* test_getntinfo */

/* Test driver for testing the public functions VSgetdatainfo, ANgetdatainfo,
   GRgetdatainfo, and Hgetntinfo. */
void
test_datainfo()
{
    /* Test VSgetdatainfo with data stored in one contiguous block */
    test_simple_vs();

    /* Test VSgetdatainfo with data might be stored in linked blocks */
    test_append_vs();

    /* Test ANgetdatainfo */
    test_annotation();

    /* Test GRgetdatainfo with images stored in one contiguous block, with
       and without compression */
    test_oneblock_ri();

    /* Test GRgetdatainfo with RI8 and RI24 */
    test_dfr8_24();

    /* Test GRgetpalinfo with RI8 and GR */
    test_getpalinfo();

    /* Test Hgetntinfo */
    test_getntinfo();
}