1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF.  The full HDF copyright notice, including       *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* $Id$ */
15 
16 /*
17 FILE
18    hcomp.c
19    HDF compressed data I/O routines
20 
21 REMARKS
22    These functions read and write compressed data to HDF data objects.
23    The compressed data objects are implemented as "special tags"
24    in the HDF file and the "H" layer I/O routines break out to the
25    functions in this module to deal with them.
26 
27 DESIGN
28    The compression I/O functions are designed as state machines.
29    There are two seperate state machines implemented, as layers
30    on top of one another.
31       The top layer is the modeling layer,
32    whose purpose is to send/receive uncompressed bytes between the higher
33    layer (the "H" layer routines) and the lower layer, the coding layer.
34    The modeling layer is constrained to look like Standard C
35    I/O functions to the upper layer, while sending data in
36    potentially unusual orders to the coding layer.  [An unusual
37    order of bytes would be a Peano or Hilbert curve instead
38    of the raster order more normally used].
39       The lower layer is the coding layer, whose purpose is to
40    send/receive bytes of data to the higher layer (the modeling
41    layer) and to send/receive bits/bytes of data to the bit I/O
42    functions after encoding them with some compression scheme.
43    Both of these layers are designed as independent state
44    machines whose state contains all the information to restart
45    at a given point.  The purpose of this is to "cache" the
46    state of each layer at certain [convenient] times in order
47    to increase performance during random I/O.
48 
49 BUGS/LIMITATIONS
50    Currently the following design limitations are still in place:
51    1 - Cannot compress an existing data element (will be fixed
52        before release)  [ I think this is done, but it needs
53        testing]
54 
55    2 - Statistic gathering from several types of compression
56        is not implemented (should be fixed before release)
57    3 - "State caching" for improved performance in not implemented,
58        although some data-structures allow for it. (should be
59        fixed before release)
60    4 - Random writing in compressed data is not supported (unlikely
61        to _ever_ be fixed)
62 
63 EXPORTED ROUTINES
64    HCcreate - create or modify an existing data element to be compressed
65 LOCAL ROUTINES
66 
67 AUTHOR
68    Quincey Koziol
69 
70 MODIFICATION HISTORY
71    9/21/93  - Starting writing specs & coding prototype
72    10/09/93 - Finished initial testing.  First version with only stdio
73               modeling and RLE coding done.
74  */
75 
76 /* General HDF includes */
77 #define COMPRESS_MASTER
78 #include "hdf.h"
79 
80 #ifdef H4_HAVE_LIBSZ
81 #include "szlib.h"
82 #endif
83 
84 /* HDF compression includes */
85 #include "hcompi.h"     /* Internal definitions for compression */
86 
87 /* Local defines */
88 #define COMP_HEADER_VERSION 0
89 #ifdef OLD_WAY
90 #define COMP_START_BLOCK    1
91 #else /* OLD_WAY */
92 #define COMP_START_BLOCK    0
93 #endif /* OLD_WAY */
94 
95 /* declaration of the functions provided in this module */
96 PRIVATE int32 HCIstaccess
97             (accrec_t * access_rec, int16 acc_mode);
98 
99 PRIVATE int32 HCIinit_coder
100             (int16 acc_mode, comp_coder_info_t * cinfo, comp_coder_t coder_type,
101              comp_info * coder_info);
102 
103 PRIVATE int32 HCIread_header
104             (accrec_t * access_rec, compinfo_t * info,
105                 comp_info * c_info, model_info * m_info);
106 
107 PRIVATE int32 HCIwrite_header
108             (atom_t file_id, compinfo_t * info, uint16 special_tag, uint16 ref,
109             comp_info *c_info, model_info *m_info);
110 
111 PRIVATE int32 HCIinit_model
112             (int16 acc_mode, comp_model_info_t * minfo, comp_model_t model_type,
113              model_info * m_info);
114 
115 /* comp_funcs -- struct of accessing functions for the compressed
116    data element function modules.  The position of each function in
117    the table is standard */
118 
119 funclist_t  comp_funcs =
120 {
121     HCPstread,
122     HCPstwrite,
123     HCPseek,
124     HCPinquire,
125     HCPread,
126     HCPwrite,
127     HCPendaccess,
128     HCPinfo,
129     NULL         /* no routine registerd */
130 };
131 
132 /* #define TESTING */
133 
134 /*--------------------------------------------------------------------------
135  NAME
136     HCIinit_coder -- Set the coder function pointers
137  USAGE
138     int32 HCIinit_coder(cinfo,coder_type,coder_info)
139     comp_coder_info_t *cinfo;   IN/OUT: pointer to coder information to modify
140     comp_coder_t coder_type;    IN: the type of encoding to use
141     comp_info *coder_info;      IN: setup information for some encoding types
142 
143  RETURNS
144     Return SUCCEED or FAIL
145  DESCRIPTION
146     Sets the encoder function pointers and the encoder type for a given
147     coder type.
148 
149  GLOBAL VARIABLES
150  COMMENTS, BUGS, ASSUMPTIONS
151     IMCOMP: Since IMCOMP is no longer supported in creating new data but the
152         library still reads existing data, it may need to be added into
153         this function somehow.  Yet, I'm not sure exactly how it should
154         be added because this function is called in both cases, writing
155         and reading.  At this time, the function will fail if it encounters
156         COMP_CODE_IMCOMP. -BMR, Jul 11, 2012
157  EXAMPLES
158  REVISION LOG
159 --------------------------------------------------------------------------*/
160 PRIVATE int32
HCIinit_coder(int16 acc_mode,comp_coder_info_t * cinfo,comp_coder_t coder_type,comp_info * c_info)161 HCIinit_coder(int16 acc_mode, comp_coder_info_t * cinfo, comp_coder_t coder_type,
162               comp_info * c_info)
163 {
164     uint32 comp_info;
165     CONSTR(FUNC, "HCIinit_coder");  /* for HERROR */
166 
167     HCget_config_info(coder_type, &comp_info);
168 /* TODO: This construct S.B.
169  *       (comp_info & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED))
170  *     but the calling code does not handle it correctly
171  */
172     if ((comp_info & COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED) == 0) {
173     /* coder not present?? */
174               HRETURN_ERROR(DFE_BADCODER, FAIL)
175     }
176 
177     switch (coder_type)
178       {     /* determine the type of encoding */
179           case COMP_CODE_NONE:      /* "none" (i.e. no) encoding */
180               cinfo->coder_type = COMP_CODE_NONE;   /* set coding type */
181               cinfo->coder_funcs = cnone_funcs;     /* set the "none" func. ptrs */
182               break;
183 
184           case COMP_CODE_RLE:   /* Run-length encoding */
185               cinfo->coder_type = COMP_CODE_RLE;    /* set coding type */
186               cinfo->coder_funcs = crle_funcs;  /* set the RLE func. ptrs */
187               break;
188 
189           case COMP_CODE_NBIT:      /* N-bit encoding */
190               cinfo->coder_type = COMP_CODE_NBIT;   /* set the coding type */
191               cinfo->coder_funcs = cnbit_funcs;     /* set the N-bit func. ptrs */
192 
193               /* copy encoding info */
194               cinfo->coder_info.nbit_info.nt = c_info->nbit.nt;
195               cinfo->coder_info.nbit_info.sign_ext = c_info->nbit.sign_ext;
196               cinfo->coder_info.nbit_info.fill_one = c_info->nbit.fill_one;
197               cinfo->coder_info.nbit_info.mask_off = c_info->nbit.start_bit;
198               cinfo->coder_info.nbit_info.mask_len = c_info->nbit.bit_len;
199               if ((cinfo->coder_info.nbit_info.nt_size
200                    = DFKNTsize(cinfo->coder_info.nbit_info.nt)) == FAIL)
201                   HRETURN_ERROR(DFE_BADNUMTYPE, FAIL);
202               break;
203 
204           case COMP_CODE_SKPHUFF:   /* Skipping Huffman encoding */
205               if(c_info->skphuff.skp_size<1)
206                   HRETURN_ERROR(DFE_BADCODER, FAIL)
207 
208               /* set the coding type and the skipping huffman func. ptrs */
209               cinfo->coder_type = COMP_CODE_SKPHUFF;
210               cinfo->coder_funcs = cskphuff_funcs;
211 
212               /* copy encoding info */
213               cinfo->coder_info.skphuff_info.skip_size = c_info->skphuff.skp_size;
214               break;
215 
216           case COMP_CODE_DEFLATE:   /* gzip 'deflate' encoding */
217         /* valid deflate levels are from 0 to 9, this error checking
218         caused the problem in HDF4r1.2 , fixed by Apu Kapadia
219         if(c_info->deflate.level<1 || c_info->deflate.level>9)
220         */
221               if(c_info->deflate.level<0 || c_info->deflate.level>9)
222                   HRETURN_ERROR(DFE_BADCODER, FAIL)
223 
224               /* set the coding type and the gzip 'deflate' func. ptrs */
225               cinfo->coder_type = COMP_CODE_DEFLATE;
226               cinfo->coder_funcs = cdeflate_funcs;
227 
228               /* copy encoding info */
229               if(acc_mode&DFACC_WRITE)
230                   cinfo->coder_info.deflate_info.deflate_level = c_info->deflate.level;
231               break;
232 
233            case COMP_CODE_SZIP:
234               /* set the coding type */
235               cinfo->coder_type = COMP_CODE_SZIP;
236 
237         /* when libsz presents, initialize other info - BMR, 08/25/2007
238         (changed from eliminating this case completely) */
239         /* completely removed the libsz limitation, we shouldn't need
240         szip library to initialize here - BMR, 10/21/2008 */
241 
242               /* set the szip func. ptrs */
243               cinfo->coder_funcs = cszip_funcs;
244 
245               /* copy encoding info */
246               cinfo->coder_info.szip_info.pixels = c_info->szip.pixels;
247               cinfo->coder_info.szip_info.bits_per_pixel = c_info->szip.bits_per_pixel;
248               cinfo->coder_info.szip_info.pixels_per_block = c_info->szip.pixels_per_block;
249               cinfo->coder_info.szip_info.pixels_per_scanline = c_info->szip.pixels_per_scanline;
250               cinfo->coder_info.szip_info.options_mask = c_info->szip.options_mask;
251               cinfo->coder_info.szip_info.buffer = NULL;
252               cinfo->coder_info.szip_info.buffer_size = 0;
253               cinfo->coder_info.szip_info.offset = 0;
254               cinfo->coder_info.szip_info.szip_state = SZIP_INIT;
255               cinfo->coder_info.szip_info.szip_dirty = SZIP_CLEAN;
256               break;
257 
258           default:
259               HRETURN_ERROR(DFE_BADCODER, FAIL)
260       }     /* end switch */
261     return (SUCCEED);
262 }   /* end HCIinit_coder() */
263 
264 /*--------------------------------------------------------------------------
265  NAME
266     HCIinit_model -- Set the model function pointers
267  USAGE
268     int32 HCIinit_model(minfo,model_type,m_info)
269     comp_model_info_t *minfo;   IN/OUT: pointer to model information to modify
270     comp_model_t model_type;    IN: the type of encoding to use
271     model_info *m_info;         IN: modeling information
272 
273  RETURNS
274     Return SUCCEED or FAIL
275  DESCRIPTION
276     Sets the modeling function pointers and the model type for a given
277     model type.
278 
279  GLOBAL VARIABLES
280  COMMENTS, BUGS, ASSUMPTIONS
281  EXAMPLES
282  REVISION LOG
283 --------------------------------------------------------------------------*/
284 PRIVATE int32
HCIinit_model(int16 acc_mode,comp_model_info_t * minfo,comp_model_t model_type,model_info * m_info)285 HCIinit_model(int16 acc_mode, comp_model_info_t * minfo, comp_model_t model_type,
286               model_info * m_info)
287 {
288     CONSTR(FUNC, "HCIinit_model");  /* for HERROR */
289 
290     /* shut compiler up */
291     acc_mode = acc_mode;
292     m_info = m_info;
293 
294     switch (model_type)
295       {     /* determine the type of modeling */
296           case COMP_MODEL_STDIO:    /* standard C stdio modeling */
297               minfo->model_type = COMP_MODEL_STDIO;     /* set model type */
298               minfo->model_funcs = mstdio_funcs;    /* set the stdio func. ptrs */
299               break;
300 
301           default:
302               HRETURN_ERROR(DFE_BADMODEL, FAIL)
303       }     /* end switch */
304 
305     return (SUCCEED);
306 }   /* end HCIinit_model() */
307 
308 /*--------------------------------------------------------------------------
309  NAME
310     HCPquery_encode_header -- Query the length of compression header for a memory buffer
311  USAGE
312     int32 HCPquery_encode_header(model_type, model_info, coder_type, coder_info)
313     comp_model_t model_type; IN: the type of modeling to use
314     model_info *m_info;      IN: Information needed for the modeling type chosen
315     comp_coder_t coder_type; IN: the type of encoding to use
316     coder_info *c_info;      IN: Information needed for the encoding type chosen
317 
318  RETURNS
319     Return the length of the buffer needed to store the compression header on
320     success (>0) or FAIL (-1)
321  DESCRIPTION
322     Determine the compression information length in a memory block.
323 
324  GLOBAL VARIABLES
325  COMMENTS, BUGS, ASSUMPTIONS
326  EXAMPLES
327  REVISION LOG
328 --------------------------------------------------------------------------*/
329 int32
HCPquery_encode_header(comp_model_t model_type,model_info * m_info,comp_coder_t coder_type,comp_info * c_info)330 HCPquery_encode_header(comp_model_t model_type, model_info * m_info,
331          comp_coder_t coder_type, comp_info * c_info)
332 {
333     CONSTR(FUNC, "HCPquery_encode_header");    /* for HERROR */
334     int32 coder_len=2;  /* # of bytes to encode coder information (2 minimum) */
335     int32 model_len=2;  /* # of bytes to encode model information (2 minimum) */
336     int32 ret_value=SUCCEED;
337 
338     /* clear error stack and validate args */
339     HEclear();
340     if (m_info==NULL || c_info==NULL)
341         HGOTO_ERROR(DFE_ARGS, FAIL);
342 
343     /* add any additional information needed for modeling type */
344     switch (model_type)
345       {
346           default:      /* no additional information needed */
347               break;
348       }     /* end switch */
349 
350     /* add any additional information needed for coding type */
351     switch (coder_type)
352       {
353           case COMP_CODE_NBIT:    /* N-bit coding needs 16 bytes of info */
354               coder_len+=16;
355               break;
356 
357           case COMP_CODE_SKPHUFF: /* Skipping Huffman coding needs 8 bytes of info */
358               coder_len+=8;
359               break;
360 
361           case COMP_CODE_DEFLATE: /* Deflation coding stores deflation level */
362               coder_len+=2;
363               break;
364 
365           case COMP_CODE_SZIP: /* Szip coding stores various szip parameters */
366         coder_len += 14;
367         break;
368 
369           case COMP_CODE_IMCOMP: /* IMCOMP is no longer supported, can only be inquired */
370               HRETURN_ERROR(DFE_BADCODER, FAIL);
371               break;
372 
373           default:      /* no additional information needed */
374               break;
375       }     /* end switch */
376 
377     ret_value=model_len+coder_len;
378 
379 done:
380     if(ret_value == FAIL)
381       { /* Error condition cleanup */
382 
383       } /* end if */
384 
385     /* Normal function cleanup */
386     return ret_value;
387 } /* end HCPquery_encode_header() */
388 
389 /*--------------------------------------------------------------------------
390  NAME
391     HCPencode_header -- Encode the compression header info to a memory buffer
392  USAGE
393     intn HCPencode_header(model_type, model_info, coder_type, coder_info)
394     void * buf;               OUT: encoded compression info header
395     comp_model_t model_type; IN: the type of modeling to use
396     model_info *m_info;      IN: Information needed for the modeling type chosen
397     comp_coder_t coder_type; IN: the type of encoding to use
398     coder_info *c_info;      IN: Information needed for the encoding type chosen
399 
400  RETURNS
401     Return SUCCEED or FAIL
402  DESCRIPTION
403     Encodes the compression information to a block in memory.
404 
405  GLOBAL VARIABLES
406  COMMENTS, BUGS, ASSUMPTIONS
407  EXAMPLES
408  REVISION LOG
409 --------------------------------------------------------------------------*/
410 intn
HCPencode_header(uint8 * p,comp_model_t model_type,model_info * m_info,comp_coder_t coder_type,comp_info * c_info)411 HCPencode_header(uint8 *p, comp_model_t model_type, model_info * m_info,
412          comp_coder_t coder_type, comp_info * c_info)
413 {
414     CONSTR(FUNC, "HCPencode_header");    /* for HERROR */
415     int32 ret_value=SUCCEED;
416 
417     /* clear error stack and validate args */
418     HEclear();
419     if (p==NULL || m_info==NULL || c_info==NULL)
420         HGOTO_ERROR(DFE_ARGS, FAIL);
421 
422     UINT16ENCODE(p, (uint16) model_type);   /* specify model type */
423     UINT16ENCODE(p, (uint16) coder_type);   /* specify coder type */
424 
425     /* add any additional information needed for modeling type */
426     switch (model_type)
427       {
428           default:      /* no additional information needed */
429               break;
430       }     /* end switch */
431 
432     /* add any additional information needed for coding type */
433     switch (coder_type)
434       {
435           case COMP_CODE_NBIT:      /* N-bit coding needs info */
436               /* specify number-type of N-bit data */
437               INT32ENCODE(p, c_info->nbit.nt);
438               /* next is the flag to indicate whether to sign extend */
439               UINT16ENCODE(p, (uint16) c_info->nbit.sign_ext);
440               /* flag to fill with 1's or 0's */
441               UINT16ENCODE(p, (uint16) c_info->nbit.fill_one);
442               /* the offset of the bits extracted */
443               INT32ENCODE(p, (int32) c_info->nbit.start_bit);
444               /* the number of bits extracted */
445               INT32ENCODE(p, (int32) c_info->nbit.bit_len);
446               break;
447 
448           case COMP_CODE_SKPHUFF:   /* Skipping Huffman coding needs info */
449               if(c_info->skphuff.skp_size<1)
450                   HRETURN_ERROR(DFE_BADCODER, FAIL)
451 
452               /* specify skipping unit size */
453               UINT32ENCODE(p, (uint32) c_info->skphuff.skp_size);
454               /* specify # of bytes compressed (not used currently) */
455               UINT32ENCODE(p, (uint32) c_info->skphuff.skp_size);
456               break;
457 
458           case COMP_CODE_DEFLATE:   /* Deflation coding stores deflation level */
459               /* valid deflate levels are from 0 to 9
460               if(c_info->deflate.level<1 || c_info->deflate.level>9)
461               */
462               if(c_info->deflate.level<0 || c_info->deflate.level>9)
463                   HRETURN_ERROR(DFE_BADCODER, FAIL)
464 
465               /* specify deflation level */
466               UINT16ENCODE(p, (uint16) c_info->deflate.level);
467               break;
468 
469           case COMP_CODE_SZIP: /* Szip coding stores various szip parameters */
470               UINT32ENCODE(p, (uint32) c_info->szip.pixels);
471               UINT32ENCODE(p, (uint32) c_info->szip.pixels_per_scanline);
472               UINT32ENCODE(p, (uint32) (c_info->szip.options_mask | SZ_H4_REV_2));
473               *p++ = (uint8) c_info->szip.bits_per_pixel;
474               *p++ = (uint8) c_info->szip.pixels_per_block;
475               break;
476 
477           case COMP_CODE_IMCOMP: /* IMCOMP is no longer supported, can only be inquired */
478               HRETURN_ERROR(DFE_BADCODER, FAIL);
479               break;
480 
481           default:      /* no additional information needed */
482               break;
483       }     /* end switch */
484 
485 done:
486     if(ret_value == FAIL)
487       { /* Error condition cleanup */
488 
489       } /* end if */
490 
491     /* Normal function cleanup */
492     return ret_value;
493 } /* end HCPencode_header() */
494 
495 /*--------------------------------------------------------------------------
496  NAME
497     HCPdecode_header -- Decode the compression header info from a memory buffer
498  USAGE
499     intn HCPdecode_header(model_type, model_info, coder_type, coder_info)
500     void * buf;                  IN: encoded compression info header
501     comp_model_t *model_type;   OUT: the type of modeling to use
502     model_info *m_info;         OUT: Information needed for the modeling type chosen
503     comp_coder_t *coder_type;   OUT: the type of encoding to use
504     coder_info *c_info;         OUT: Information needed for the encoding type chosen
505 
506  RETURNS
507     Return SUCCEED or FAIL
508  DESCRIPTION
509     Decodes the compression information from a block in memory.
510 
511  GLOBAL VARIABLES
512  COMMENTS, BUGS, ASSUMPTIONS
513  EXAMPLES
514  REVISION LOG
515 --------------------------------------------------------------------------*/
516 intn
HCPdecode_header(uint8 * p,comp_model_t * model_type,model_info * m_info,comp_coder_t * coder_type,comp_info * c_info)517 HCPdecode_header(uint8 *p, comp_model_t *model_type, model_info * m_info,
518          comp_coder_t *coder_type, comp_info * c_info)
519 {
520     CONSTR(FUNC, "HCPdecode_header");    /* for HERROR */
521     uint16 m_type, c_type;
522     int32 ret_value=SUCCEED;
523 
524     /* clear error stack and validate args */
525     HEclear();
526     if (p==NULL || model_type==NULL || m_info==NULL || coder_type==NULL || c_info==NULL)
527         HGOTO_ERROR(DFE_ARGS, FAIL);
528 
529     UINT16DECODE(p, m_type);     /* get model type */
530     *model_type=(comp_model_t)m_type;
531     UINT16DECODE(p, c_type);     /* get encoding type */
532     *coder_type=(comp_coder_t)c_type;
533 
534     /* read any additional information needed for modeling type */
535     switch (*model_type)
536       {
537           default:      /* no additional information needed */
538               break;
539       }     /* end switch */
540 
541     /* read any additional information needed for coding type */
542     switch (*coder_type)
543       {
544           case COMP_CODE_NBIT:      /* Obtain info for N-bit coding */
545               {
546                   uint16      s_ext;    /* temp. var for sign extend */
547                   uint16      f_one;    /* temp. var for fill one */
548                   int32       m_off, m_len;     /* temp. var for mask offset and len */
549 
550                   /* number-type of N-bit data */
551                   INT32DECODE(p, c_info->nbit.nt);
552                   /* next is the flag to indicate whether to sign extend */
553                   UINT16DECODE(p, s_ext);
554                   c_info->nbit.sign_ext = (intn) s_ext;
555                   /* flag to indicate whether to fill with 1's or 0's */
556                   UINT16DECODE(p, f_one);
557                   c_info->nbit.fill_one = (intn) f_one;
558                   /* offset of the bits extracted */
559                   INT32DECODE(p, m_off);
560                   c_info->nbit.start_bit = (intn) m_off;
561                   /* number of bits extracted */
562                   INT32DECODE(p, m_len);
563                   c_info->nbit.bit_len = (intn) m_len;
564               }     /* end case */
565               break;
566 
567           case COMP_CODE_SKPHUFF: /* Obtain info for Skipping Huffman coding */
568               {
569                   uint32      skp_size,     /* size of skipping unit */
570                               comp_size;    /* # of bytes to compress */
571 
572                   /* specify skipping unit size */
573                   UINT32DECODE(p, skp_size);
574                   /* specify # of bytes of skipping data to compress */
575                   UINT32DECODE(p, comp_size);   /* ignored for now */
576                   c_info->skphuff.skp_size = (intn) skp_size;
577               }     /* end case */
578               break;
579 
580           case COMP_CODE_DEFLATE: /* Obtains deflation level for Deflation coding */
581               {
582                   uint16      level;    /* deflation level */
583 
584                   /* specify deflation level */
585                   UINT16DECODE(p, level);
586                   c_info->deflate.level = (intn) level;
587               }     /* end case */
588               break;
589 
590           case COMP_CODE_SZIP: /* Obtains szip parameters for Szip coding */
591         {
592                   UINT32DECODE(p, c_info->szip.pixels);
593                   UINT32DECODE(p, c_info->szip.pixels_per_scanline);
594                   UINT32DECODE(p, c_info->szip.options_mask);
595                   c_info->szip.bits_per_pixel = *p++;
596                   c_info->szip.pixels_per_block = *p++;
597         }
598               break;
599 
600           default:      /* no additional information needed */
601                         /* this includes RLE, JPEG, and IMCOMP */
602               break;
603       }     /* end switch */
604 
605 done:
606     if(ret_value == FAIL)
607       { /* Error condition cleanup */
608 
609       } /* end if */
610 
611     /* Normal function cleanup */
612     return ret_value;
613 } /* end HCPdecode_header() */
614 
615 /*--------------------------------------------------------------------------
616  NAME
617     HCIwrite_header -- Write the compression header info to a file
618  USAGE
619     int32 HCIwrite_header(access_rec,info,special_tag,ref)
620     atom_t file_id;         IN: File ID of the file to write the header to
621     compinfo_t *info;       IN: ptr the compression information
622     uint16 special_tag,ref; IN: the tag/ref of the compressed element
623     coder_info *c_info;     IN: Information needed for the encoding type chosen
624     model_info *m_info;     IN: Information needed for the modeling type chosen
625 
626  RETURNS
627     Return SUCCEED or FAIL
628  DESCRIPTION
629     Writes the compression information to a new block in the HDF file.
630 
631  GLOBAL VARIABLES
632  COMMENTS, BUGS, ASSUMPTIONS
633  EXAMPLES
634  REVISION LOG
635 --------------------------------------------------------------------------*/
636 PRIVATE int32
HCIwrite_header(atom_t file_id,compinfo_t * info,uint16 special_tag,uint16 ref,comp_info * c_info,model_info * m_info)637 HCIwrite_header(atom_t file_id, compinfo_t * info, uint16 special_tag, uint16 ref, comp_info *c_info, model_info *m_info)
638 {
639     CONSTR(FUNC, "HCIwrite_header");    /* for HERROR */
640     int32       dd_aid;         /* AID for writing the special info */
641     uint8      *p;              /* pointer to the temporary buffer */
642     uint8       local_ptbuf[32];
643     int32       header_len;     /* how many bytes the header is */
644     int32       ret_value=SUCCEED;
645 
646     /* write special element info to the file */
647     p = local_ptbuf;
648     INT16ENCODE(p, SPECIAL_COMP);   /* specify special tag type */
649     UINT16ENCODE(p, COMP_HEADER_VERSION);   /* specify header version */
650     INT32ENCODE(p, info->length);   /* write length of un-comp. data */
651     UINT16ENCODE(p, (uint16) info->comp_ref);   /* specify ref # of comp. data */
652 #ifdef OLD_WAY
653     UINT16ENCODE(p, (uint16) info->minfo.model_type);   /* specify model type */
654     UINT16ENCODE(p, (uint16) info->cinfo.coder_type);   /* specify coder type */
655 
656     /* write any additional information needed for modeling type */
657     switch (info->minfo.model_type)
658       {
659           default:      /* no additional information needed */
660               break;
661       }     /* end switch */
662 
663     /* write any additional information needed for coding type */
664     switch (info->cinfo.coder_type)
665       {
666           case COMP_CODE_NBIT:      /* N-bit coding needs info */
667               /* specify number-type of N-bit data */
668               INT32ENCODE(p, info->cinfo.coder_info.nbit_info.nt);
669               /* next is the flag to indicate whether to sign extend */
670               UINT16ENCODE(p, (uint16) info->cinfo.coder_info.nbit_info.sign_ext);
671               /* flag to fill with 1's or 0's */
672               UINT16ENCODE(p, (uint16) info->cinfo.coder_info.nbit_info.fill_one);
673               /* the offset of the bits extracted */
674               INT32ENCODE(p, (int32) info->cinfo.coder_info.nbit_info.mask_off);
675               /* the number of bits extracted */
676               INT32ENCODE(p, (int32) info->cinfo.coder_info.nbit_info.mask_len);
677               break;
678 
679           case COMP_CODE_SKPHUFF:   /* Skipping Huffman coding needs info */
680               /* specify skipping unit size */
681               UINT32ENCODE(p, (uint32) info->cinfo.coder_info.skphuff_info.skip_size);
682               /* specify # of bytes compressed (not used currently) */
683               UINT32ENCODE(p, (uint32) info->cinfo.coder_info.skphuff_info.skip_size);
684               break;
685 
686           case COMP_CODE_SZIP:
687               INT32ENCODE(p, (int32) c_info->szip.pixels);
688               INT32ENCODE(p, (int32) c_info->szip.pixels_per_scanline);
689               INT32ENCODE(p, (int32) c_info->szip.options_mask);
690               INT32ENCODE(p, (int32) c_info->szip.bits_per_pixel);
691               INT32ENCODE(p, (int32) c_info->szip.pixels_per_block);
692               break;
693 
694           case COMP_CODE_IMCOMP: /* IMCOMP is no longer supported, can only be inquired */
695               HRETURN_ERROR(DFE_BADCODER, FAIL);
696               break;
697 
698           default:      /* no additional information needed */
699               break;
700       }     /* end switch */
701 #else /* OLD_WAY */
702     if((header_len=HCPquery_encode_header(info->minfo.model_type,
703             m_info,info->cinfo.coder_type,c_info))==FAIL)
704         HGOTO_ERROR(DFE_INTERNAL, FAIL);
705     if(HCPencode_header(p,info->minfo.model_type,m_info,
706             info->cinfo.coder_type,c_info)==FAIL)
707         HGOTO_ERROR(DFE_INTERNAL, FAIL);
708     p+=header_len;
709 #endif /* OLD_WAY */
710 
711     /* write the special info structure to fill */
712     if((dd_aid=Hstartaccess(file_id,special_tag,ref,DFACC_ALL))==FAIL)
713         HGOTO_ERROR(DFE_CANTACCESS, FAIL);
714     if (Hwrite(dd_aid, p-local_ptbuf, local_ptbuf) == FAIL)
715         HGOTO_ERROR(DFE_WRITEERROR, FAIL);
716     if(Hendaccess(dd_aid)==FAIL)
717         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
718 
719 done:
720     if(ret_value == FAIL)
721       { /* Error condition cleanup */
722 
723       } /* end if */
724 
725     /* Normal function cleanup */
726     return ret_value;
727 }   /* end HCIwrite_header() */
728 
729 /*--------------------------------------------------------------------------
730  NAME
731     HCIread_header -- Read the compression header info from a file
732  USAGE
733     int32 HCIread_header(file_rec,access_rec,info,comp_info,model_info)
734     accrec_t *access_rec;   IN: ptr to the access element record
735     compinfo_t *info;       IN: ptr the compression information
736     comp_info *comp_info;   IN/OUT: ptr to encoding info
737     model_info *model_info; IN/OUT: ptr to modeling info
738  RETURNS
739     Return SUCCEED or FAIL
740  DESCRIPTION
741     Parses the compression header from a data element in an HDF file.
742 
743  GLOBAL VARIABLES
744  COMMENTS, BUGS, ASSUMPTIONS
745  EXAMPLES
746  REVISION LOG
747 --------------------------------------------------------------------------*/
748 PRIVATE int32
HCIread_header(accrec_t * access_rec,compinfo_t * info,comp_info * c_info,model_info * m_info)749 HCIread_header(accrec_t * access_rec,
750                compinfo_t * info, comp_info * c_info, model_info * m_info)
751 {
752     CONSTR(FUNC, "HCIread_header");     /* for HERROR */
753     uint16      header_version; /* version of the compression header */
754     uint8      *p;              /* pointer to the temporary buffer */
755     uint8      *local_ptbuf;
756     int32       ret_value=SUCCEED;
757 
758     /* shut compiler up */
759     m_info = m_info;
760 
761     /* Get the compression header (description record) */
762     HPread_drec(access_rec->file_id, access_rec->ddid, &local_ptbuf);
763 
764     /* Extract info */
765     p = local_ptbuf+2;
766     UINT16DECODE(p, header_version);    /* get compression version */
767     INT32DECODE(p, info->length);   /* get _uncompressed_ data length */
768     UINT16DECODE(p, info->comp_ref);    /* get ref # of comp. data */
769 
770     /* Decode the compression header */
771     if(HCPdecode_header(p,&(info->minfo.model_type),m_info,&(info->cinfo.coder_type),c_info)==FAIL)
772         HGOTO_ERROR(DFE_INTERNAL, FAIL);
773     HDfree(local_ptbuf);
774 
775 done:
776     if(ret_value == FAIL)
777       { /* Error condition cleanup */
778 
779       } /* end if */
780 
781     /* Normal function cleanup */
782     return ret_value;
783 }   /* end HCIread_header() */
784 
785 /*--------------------------------------------------------------------------
786  NAME
787     HCcreate -- Create a compressed data element
788  USAGE
789     int32 HCcreate(id,tag,ref,model_type,coder_type)
790     int32 id;                IN: the file id to create the data in
791     uint16 tag,ref;          IN: the tag/ref pair which is to be compressed
792     comp_model_t model_type; IN: the type of modeling to use
793     model_info *m_info;      IN: Information needed for the modeling type chosen
794     comp_coder_t coder_type; IN: the type of encoding to use
795     coder_info *c_info;      IN: Information needed for the encoding type chosen
796  RETURNS
797     Return an AID to the newly created compressed element, FAIL on error.
798  DESCRIPTION
799     Create a compressed data element.  If that data element already
800     exists, we will compress that data element if it is currently un-compresed,
801     or return FAIL if it is already compressed.
802 
803  GLOBAL VARIABLES
804  COMMENTS, BUGS, ASSUMPTIONS
805  EXAMPLES
806  REVISION LOG
807 --------------------------------------------------------------------------*/
808 int32
HCcreate(int32 file_id,uint16 tag,uint16 ref,comp_model_t model_type,model_info * m_info,comp_coder_t coder_type,comp_info * c_info)809 HCcreate(int32 file_id, uint16 tag, uint16 ref, comp_model_t model_type,
810          model_info * m_info, comp_coder_t coder_type,
811          comp_info * c_info)
812 {
813     CONSTR(FUNC, "HCcreate");   /* for HERROR */
814     filerec_t  *file_rec;       /* file record */
815     accrec_t   *access_rec=NULL;/* access element record */
816     compinfo_t *info=NULL;      /* special element information */
817     atom_t      data_id=FAIL;   /* dd ID of existing regular element */
818     int32       data_len;        /* length of the data we are checking */
819     uint16      special_tag;    /* special version of tag */
820     void *       buf = NULL;      /* temporary buffer */
821     int32       ret_value=SUCCEED;
822 
823     /* clear error stack and validate args */
824     HEclear();
825     file_rec = HAatom_object(file_id);
826     if (BADFREC(file_rec) || SPECIALTAG(tag)
827             || (special_tag = MKSPECIALTAG(tag)) == DFTAG_NULL)
828         HRETURN_ERROR(DFE_ARGS, FAIL);
829 
830     /* chech for access permission */
831     if (!(file_rec->access & DFACC_WRITE))
832         HRETURN_ERROR(DFE_DENIED, FAIL);
833 
834     /* get a slot in the access records table */
835     if (NULL == (access_rec = HIget_access_rec()))
836         HRETURN_ERROR(DFE_TOOMANY, FAIL);
837 
838     /* search for identical dd */
839     if ((data_id=HTPselect(file_rec,tag,ref))!=FAIL)
840       {
841           /* Check if the element is already special */
842           if (HTPis_special(data_id)==TRUE)
843             {
844                 if (HTPendaccess(data_id) == FAIL)
845                     HGOTO_ERROR(DFE_CANTFLUSH, FAIL);
846                 HGOTO_ERROR(DFE_CANTMOD, FAIL);
847             }   /* end if */
848 
849           /* get the info for the dataset */
850           if(HTPinquire(data_id,NULL,NULL,NULL,&data_len)==FAIL)
851             {
852                 if (HTPendaccess(data_id) == FAIL)
853                     HGOTO_ERROR(DFE_CANTFLUSH, FAIL);
854                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
855             } /* end if */
856 
857           if ((buf = HDmalloc((uint32) data_len)) == NULL)
858               HGOTO_ERROR(DFE_NOSPACE, FAIL);
859           if (Hgetelement(file_id, tag, ref, buf) == FAIL)
860               HGOTO_ERROR(DFE_READERROR, FAIL);
861           /* Delete the old DD from the file and memory hash table */
862           if (FAIL == HTPdelete(data_id))
863               HGOTO_ERROR(DFE_CANTDELDD, FAIL);
864 
865       } /* end if */
866 
867     /* set up the special element information and write it to file */
868     info = (compinfo_t *) HDmalloc(sizeof(compinfo_t));
869     access_rec->special_info = info;
870     if (info == NULL)
871           HGOTO_ERROR(DFE_NOSPACE, FAIL);
872 
873     info->length = (data_id!=FAIL) ? data_len : COMP_START_BLOCK;
874 
875     /* set up compressed special info structure */
876     info->attached = 1;
877     info->comp_ref = Htagnewref(file_id,DFTAG_COMPRESSED);  /* get the new reference # */
878     if(HCIinit_model(DFACC_RDWR, &(info->minfo), model_type, m_info)==FAIL)
879         HGOTO_ERROR(DFE_MINIT,FAIL);
880     if(HCIinit_coder(DFACC_RDWR, &(info->cinfo), coder_type, c_info)==FAIL)
881         HGOTO_ERROR(DFE_CINIT,FAIL);
882 
883     if (HCIwrite_header(file_id, info, special_tag, ref, c_info, m_info) == FAIL)
884           HGOTO_ERROR(DFE_WRITEERROR, FAIL);
885 
886     /* update access record and file record */
887     if((access_rec->ddid=HTPselect(file_rec,tag,ref))==FAIL)
888         HGOTO_ERROR(DFE_INTERNAL, FAIL);
889     access_rec->special_func = &comp_funcs;
890     access_rec->special = SPECIAL_COMP;
891     access_rec->posn = 0;
892     access_rec->access = DFACC_RDWR;
893     access_rec->file_id = file_id;
894     access_rec->appendable = FALSE;     /* start data as non-appendable */
895     file_rec->attach++;
896 
897     /* propagate the initialization down to the modeling layer */
898     if ((*(info->minfo.model_funcs.stwrite))(access_rec) == FAIL)
899           HGOTO_ERROR(DFE_MODEL, FAIL);
900 
901     /* compress the old DD and get rid of it, if there was one */
902     if (data_id != FAIL)
903       {
904           /* write the data through to the compression layer */
905           if (HCPwrite(access_rec, data_len, buf) == FAIL)
906               HGOTO_ERROR(DFE_MODEL, FAIL);
907 
908           /* seek back to the beginning of the data through to the compression layer */
909           if (HCPseek(access_rec, 0, DF_START) == FAIL)
910               HGOTO_ERROR(DFE_MODEL, FAIL);
911       }     /* end if */
912 
913     ret_value=HAregister_atom(AIDGROUP,access_rec);
914 
915 done:
916     if(ret_value == FAIL)
917       { /* Error condition cleanup */
918         if(access_rec!=NULL)
919             HIrelease_accrec_node(access_rec);
920         if(info!=NULL)
921             HDfree(info);
922       } /* end if */
923 
924     /* Normal function cleanup */
925     if (buf != NULL)
926         HDfree(buf);
927 
928     return ret_value;
929 }   /* end HCcreate() */
930 
931 /*--------------------------------------------------------------------------
932  NAME
933     HCPgetcompress -- Retrieves compression information of an element
934  USAGE
935     intn HCPgetcompress(aid, coder_type, c_info)
936     int32 aid;                  IN: access record ID
937     comp_coder_t* coder_type;   OUT: the type of compression
938     comp_info* c_info;          OUT: ptr to compression information
939                                 structure for storing the retrieved info
940  RETURNS
941     SUCCEED/FAIL
942  DESCRIPTION
943     This routine retrieves the compression type and the compression
944     information of the element, identified by 'aid'.  The routine is
945     used by GRgetcompinfo and SDgetcompinfo at this time.
946 
947  GLOBAL VARIABLES
948  COMMENTS, BUGS, ASSUMPTIONS
949  EXAMPLES
950  REVISION LOG
951     July 2001: Added to fix bug #307 - BMR
952     Dec. 2004: Changed name to HCPgetcompress, to be consistent with other
953                practice.  REM
954 --------------------------------------------------------------------------*/
955 intn
HCPgetcompress(int32 file_id,uint16 data_tag,uint16 data_ref,comp_coder_t * comp_type,comp_info * c_info)956 HCPgetcompress(int32 file_id,
957               uint16 data_tag, uint16 data_ref,
958               comp_coder_t* comp_type,  /* OUT: compression type */
959               comp_info* c_info)        /* OUT: retrieved compression info */
960 {
961     CONSTR(FUNC, "HCPgetcompress");   /* for HGOTO_ERROR */
962     int32   aid=0, status;
963     accrec_t*    access_rec=NULL;/* access element record */
964     compinfo_t*  info=NULL;  /* compressed element information */
965     model_info  m_info;         /* modeling information - dummy */
966     int32       ret_value=SUCCEED;
967 
968     /* clear error stack */
969     HEclear();
970 
971     /* start read access on the access record of the data element, which
972        is being inquired for its compression information */
973     aid = Hstartread(file_id, data_tag, data_ref);
974 
975     /* get the access_rec pointer */
976     access_rec = HAatom_object(aid);
977     if (access_rec == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
978 
979     /* if the element is compressed, get the compression info as requested*/
980     if (access_rec->special == SPECIAL_COMP)
981     {
982         info = (compinfo_t *) access_rec->special_info;
983         if (info == NULL) HGOTO_ERROR(DFE_COMPINFO, FAIL);
984 
985         status = HCIread_header(access_rec, info, c_info, &m_info);
986         if (status == FAIL) HGOTO_ERROR(DFE_COMPINFO, FAIL);
987 
988         /* get the compression type */
989         *comp_type = info->cinfo.coder_type;
990 
991     }  /* end if element is compressed */
992 
993     /* if the element is chunked, call HMCgetcompress to get the
994     compression info as appropriate */
995     else if (access_rec->special == SPECIAL_CHUNKED)
996     {
997     status = HMCgetcompress(access_rec, comp_type, c_info);
998         if (status == FAIL) HGOTO_ERROR(DFE_COMPINFO, FAIL);
999     }
1000 
1001     /* flag the error when attempting to get compression info on a
1002        non-compressed element */
1003     else
1004     /* EIP 9/16/03  Fail but return compression type COMP_CODE_NONE
1005        instead of junk in this case.
1006     */
1007      {
1008         /*Mac OSX screams here (comp_coder_t)*comp_type = COMP_CODE_NONE; */
1009         *comp_type = COMP_CODE_NONE;
1010         HGOTO_ERROR(DFE_ARGS, FAIL);
1011      }
1012     /* end access to the aid appropriately */
1013     if (Hendaccess(aid)== FAIL)
1014         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1015 
1016 done:
1017   if(ret_value == FAIL)
1018     { /* Error condition cleanup */
1019        /* end access to the aid if it's been accessed */
1020         if (aid != 0)
1021             if (Hendaccess(aid)== FAIL)
1022                 HERROR(DFE_CANTENDACCESS);
1023     } /* end if */
1024 
1025   /* Normal function cleanup */
1026   return ret_value;
1027 } /* HCPgetcompress */
1028 
1029 
1030 /*--------------------------------------------------------------------------
1031  NAME
1032     HCPgetcompinfo -- Retrieves compression information of an element
1033  USAGE
1034     intn HCPgetcompinfo(aid, coder_type, c_info)
1035     int32 aid;                  IN: access record ID
1036     comp_coder_t* coder_type;   OUT: the type of compression
1037     comp_info* c_info;          OUT: ptr to compression information
1038                                 structure for storing the retrieved info
1039  RETURNS
1040     SUCCEED/FAIL
1041  DESCRIPTION
1042     This routine retrieves the compression type and the compression
1043     information of the element, identified by 'aid'.  The routine is
1044     used by GRgetcompinfo and SDgetcompinfo at this time.
1045 
1046  GLOBAL VARIABLES
1047  COMMENTS, BUGS, ASSUMPTIONS
1048  EXAMPLES
1049  REVISION LOG
1050     July 2001: Added to fix bug #307 - BMR
1051     Dec. 2004: Changed name to HCPgetcompress, to be consistent with other
1052                practice.  REM
1053     Apr. 2005:    HCPgetcompinfo was added to fix bugzilla #130 and may replace
1054         HCPgetcompress in the future because HCPgetcompress did not
1055         behave correctly.  The revision logs above are carried over
1056         from HCPgetcompress for the records.
1057 --------------------------------------------------------------------------*/
1058 intn
HCPgetcompinfo(int32 file_id,uint16 data_tag,uint16 data_ref,comp_coder_t * comp_type,comp_info * c_info)1059 HCPgetcompinfo(int32 file_id,
1060               uint16 data_tag, uint16 data_ref,
1061               comp_coder_t* comp_type,  /* OUT: compression type */
1062               comp_info* c_info)        /* OUT: retrieved compression info */
1063 {
1064     CONSTR(FUNC, "HCPgetcompinfo");    /* for HGOTO_ERROR */
1065     int32   aid=0, status;
1066     accrec_t*    access_rec=NULL;    /* access element record */
1067     compinfo_t*  info=NULL;        /* compressed element information */
1068     comp_coder_t temp_coder=COMP_CODE_NONE;
1069     model_info  m_info;            /* modeling information - dummy */
1070     intn       ret_value=SUCCEED;
1071 
1072     /* clear error stack */
1073     HEclear();
1074 
1075     /* check the output arguments */
1076     if (comp_type == NULL || c_info == NULL)
1077         HGOTO_ERROR(DFE_ARGS, FAIL);
1078 
1079     /* start read access on the access record of the data element, which
1080        is being inquired for its compression information */
1081     aid = Hstartread(file_id, data_tag, data_ref);
1082 
1083     /* get the access_rec pointer */
1084     access_rec = HAatom_object(aid);
1085     if (access_rec == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
1086 
1087     /* if the element is compressed, get the compression info as requested */
1088     if (access_rec->special == SPECIAL_COMP)
1089     {
1090         info = (compinfo_t *) access_rec->special_info;
1091         if (info == NULL) HGOTO_ERROR(DFE_COMPINFO, FAIL);
1092 
1093         status = HCIread_header(access_rec, info, c_info, &m_info);
1094         if (status == FAIL) HGOTO_ERROR(DFE_COMPINFO, FAIL);
1095 
1096         /* get the compression type */
1097         temp_coder = info->cinfo.coder_type;
1098 
1099     }  /* end if element is compressed */
1100 
1101     /* if the element is chunked, call HMCgetcompress to get the
1102     compression info as appropriate */
1103     else if (access_rec->special == SPECIAL_CHUNKED)
1104     {
1105     status = HMCgetcompress(access_rec, &temp_coder, c_info);
1106         if (status == FAIL) HGOTO_ERROR(DFE_COMPINFO, FAIL);
1107     }
1108 
1109     /* return COMP_CODE_NONE for a non-compressed element */
1110     /* Note: SPECIAL_COMPRAS may need special handling */
1111     else if (access_rec->special == SPECIAL_LINKED ||
1112              access_rec->special == SPECIAL_EXT ||
1113              access_rec->special == SPECIAL_VLINKED ||
1114              access_rec->special == SPECIAL_BUFFERED ||
1115              access_rec->special == SPECIAL_COMPRAS ||
1116              access_rec->special == 0)
1117     {
1118         temp_coder = COMP_CODE_NONE;
1119     }
1120 
1121     /* flag the error when access_rec->special is not something valid */
1122     else
1123     {
1124     temp_coder = COMP_CODE_INVALID;
1125         HGOTO_ERROR(DFE_ARGS, FAIL);
1126     }
1127     /* end access to the aid appropriately */
1128     if (Hendaccess(aid)== FAIL)
1129         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1130 
1131     if (comp_type != NULL) *comp_type = temp_coder;
1132 
1133 done:
1134   if(ret_value == FAIL)
1135     { /* Error condition cleanup */
1136        /* end access to the aid if it's been accessed */
1137         if (aid != 0)
1138             if (Hendaccess(aid)== FAIL)
1139                 HERROR(DFE_CANTENDACCESS);
1140     } /* end if */
1141 
1142   /* Normal function cleanup */
1143   return ret_value;
1144 } /* HCPgetcompinfo */
1145 
1146 /*--------------------------------------------------------------------------
1147  NAME
1148     HCIstaccess -- Start accessing a compressed data element.
1149  USAGE
1150     int32 HCIstaccess(access_rec, access)
1151     accrec_t *access_rec;   IN: the access record of the data element
1152     int16 access;           IN: the type of access wanted
1153  RETURNS
1154     Returns an AID or FAIL
1155  DESCRIPTION
1156     Common code called by HCIstread and HCIstwrite
1157 
1158  GLOBAL VARIABLES
1159  COMMENTS, BUGS, ASSUMPTIONS
1160  EXAMPLES
1161  REVISION LOG
1162 --------------------------------------------------------------------------*/
1163 PRIVATE int32
HCIstaccess(accrec_t * access_rec,int16 acc_mode)1164 HCIstaccess(accrec_t * access_rec, int16 acc_mode)
1165 {
1166     CONSTR(FUNC, "HCIstaccess");    /* for HERROR */
1167     compinfo_t *info=NULL;      /* special element information */
1168     filerec_t  *file_rec;       /* file record */
1169     comp_info   c_info;         /* encoding information from the header */
1170     model_info  m_info;         /* modeling information from the header */
1171     int32       ret_value=SUCCEED;
1172 
1173     /* get file record and validate */
1174     file_rec = HAatom_object(access_rec->file_id);
1175     if (BADFREC(file_rec) || !(file_rec->access & acc_mode))
1176         HRETURN_ERROR(DFE_ARGS, FAIL);
1177 
1178     /* intialize the access record */
1179     access_rec->special = SPECIAL_COMP;
1180     access_rec->posn = 0;
1181     access_rec->access = (uint32)(acc_mode|DFACC_READ);
1182 
1183     /* get the special info record */
1184     access_rec->special_info = HDmalloc(sizeof(compinfo_t));
1185     info = (compinfo_t *) access_rec->special_info;
1186     if (info == NULL)
1187         HGOTO_ERROR(DFE_NOSPACE, FAIL);
1188 
1189     if (HCIread_header(access_rec, info, &c_info, &m_info) == FAIL)
1190           HGOTO_ERROR(DFE_COMPINFO, FAIL);
1191     info->attached = 1;
1192     if (HCIinit_model(acc_mode,&(info->minfo), info->minfo.model_type, &m_info) == FAIL)
1193           HRETURN_ERROR(DFE_MINIT, FAIL);
1194     if (HCIinit_coder(acc_mode,&(info->cinfo), info->cinfo.coder_type, &c_info) == FAIL)
1195           HRETURN_ERROR(DFE_CINIT, FAIL);
1196 
1197     file_rec->attach++;
1198 
1199     ret_value=HAregister_atom(AIDGROUP,access_rec);
1200 
1201 done:
1202     if(ret_value == FAIL)
1203       { /* Error condition cleanup */
1204         if(info!=NULL)
1205             HDfree(info);
1206       } /* end if */
1207 
1208     /* Normal function cleanup */
1209     return ret_value;
1210 }   /* end HCIstaccess() */
1211 
1212 /*--------------------------------------------------------------------------
1213  NAME
1214     HCPstread -- Start read access on a compressed data element.
1215  USAGE
1216     int32 HCPstread(access_rec)
1217     accrec_t *access_rec;   IN: the access record of the data element
1218  RETURNS
1219     Returns an AID or FAIL
1220  DESCRIPTION
1221     Start read access on a compressed data element.
1222 
1223  GLOBAL VARIABLES
1224  COMMENTS, BUGS, ASSUMPTIONS
1225  EXAMPLES
1226  REVISION LOG
1227 --------------------------------------------------------------------------*/
1228 int32
HCPstread(accrec_t * access_rec)1229 HCPstread(accrec_t * access_rec)
1230 {
1231     CONSTR(FUNC, "HCPstread");  /* for HERROR */
1232     compinfo_t *info;           /* information on the special element */
1233     int32       ret_value;      /* AID to return */
1234 
1235     if ((ret_value = HCIstaccess(access_rec, DFACC_READ)) == FAIL)
1236         HGOTO_ERROR(DFE_DENIED, FAIL);
1237     info = (compinfo_t *) access_rec->special_info;
1238     if ((*(info->minfo.model_funcs.stread)) (access_rec) == FAIL)
1239         HGOTO_ERROR(DFE_MODEL, FAIL);
1240 
1241 done:
1242     if(ret_value == FAIL)
1243       { /* Error condition cleanup */
1244 
1245       } /* end if */
1246 
1247     /* Normal function cleanup */
1248     return ret_value;
1249 }   /* end HCPstread() */
1250 
1251 /*--------------------------------------------------------------------------
1252  NAME
1253     HCPstwrite -- Start write access on a compressed data element.
1254  USAGE
1255     int32 HCPstwrite(access_rec)
1256     accrec_t *access_rec;   IN: the access record of the data element
1257  RETURNS
1258     Returns an AID or FAIL
1259  DESCRIPTION
1260     Start write access on a compressed data element.
1261 
1262  GLOBAL VARIABLES
1263  COMMENTS, BUGS, ASSUMPTIONS
1264  EXAMPLES
1265  REVISION LOG
1266 --------------------------------------------------------------------------*/
1267 int32
HCPstwrite(accrec_t * access_rec)1268 HCPstwrite(accrec_t * access_rec)
1269 {
1270     CONSTR(FUNC, "HCPstwrite");     /* for HERROR */
1271     compinfo_t *info;               /* information on the special element */
1272     int32       ret_value;          /* AID to return */
1273 
1274     if ((ret_value = HCIstaccess(access_rec, DFACC_WRITE)) == FAIL)
1275         HGOTO_ERROR(DFE_DENIED, FAIL);
1276     info = (compinfo_t *) access_rec->special_info;
1277     if ((*(info->minfo.model_funcs.stwrite)) (access_rec) == FAIL)
1278         HGOTO_ERROR(DFE_MODEL, FAIL);
1279 
1280 done:
1281     if(ret_value == FAIL)
1282       { /* Error condition cleanup */
1283 
1284       } /* end if */
1285 
1286     /* Normal function cleanup */
1287     return ret_value;
1288 }   /* end HCPstwrite() */
1289 
1290 /*--------------------------------------------------------------------------
1291  NAME
1292     HCPseek -- Seek to offset within the data element
1293  USAGE
1294     int32 HCPseek(access_rec,offset,origin)
1295     accrec_t *access_rec;   IN: the access record of the data element
1296     int32 offset;       IN: the offset in bytes from the origin specified
1297     intn origin;        IN: the origin to seek from
1298  RETURNS
1299     Returns SUCCEED or FAIL
1300  DESCRIPTION
1301     Seek to a position with a compressed data element.
1302 
1303  GLOBAL VARIABLES
1304  COMMENTS, BUGS, ASSUMPTIONS
1305  EXAMPLES
1306  REVISION LOG
1307 --------------------------------------------------------------------------*/
1308 int32
HCPseek(accrec_t * access_rec,int32 offset,intn origin)1309 HCPseek(accrec_t * access_rec, int32 offset, intn origin)
1310 {
1311     CONSTR(FUNC, "HCPseek");    /* for HERROR */
1312     compinfo_t *info;           /* information on the special element */
1313     int32       ret_value;
1314 
1315     /* Adjust offset according to origin.  There is no upper bound to posn */
1316     if (origin == DF_CURRENT)
1317         offset += access_rec->posn;
1318     if (origin == DF_END)
1319         offset += ((compinfo_t *) (access_rec->special_info))->length;
1320     if (offset < 0)
1321         HGOTO_ERROR(DFE_RANGE, FAIL);
1322 
1323     info = (compinfo_t *) access_rec->special_info;
1324     if ((ret_value = (*(info->minfo.model_funcs.seek)) (access_rec, offset, origin)) == FAIL)
1325         HGOTO_ERROR(DFE_MODEL, FAIL);
1326 
1327     /* set the offset */
1328     access_rec->posn = offset;
1329 
1330 done:
1331     if(ret_value == FAIL)
1332       { /* Error condition cleanup */
1333 
1334       } /* end if */
1335 
1336     /* Normal function cleanup */
1337     return ret_value;
1338 }   /* end HCPseek() */
1339 
1340 /*--------------------------------------------------------------------------
1341  NAME
1342     HCPread -- Read in a portion of data from a compressed data element.
1343  USAGE
1344     int32 HCPread(access_rec,length,data)
1345     accrec_t *access_rec;   IN: the access record of the data element
1346     int32 length;           IN: the number of bytes to read
1347     void * data;             OUT: the buffer to place the bytes read
1348  RETURNS
1349     Returns the number of bytes read or FAIL
1350  DESCRIPTION
1351     Read in a number of bytes from a compressed data element.
1352 
1353  GLOBAL VARIABLES
1354  COMMENTS, BUGS, ASSUMPTIONS
1355  EXAMPLES
1356  REVISION LOG
1357 --------------------------------------------------------------------------*/
1358 int32
HCPread(accrec_t * access_rec,int32 length,void * data)1359 HCPread(accrec_t * access_rec, int32 length, void * data)
1360 {
1361     CONSTR(FUNC, "HCPread");    /* for HERROR */
1362     compinfo_t *info;           /* information on the special element */
1363     int32       ret_value;
1364 
1365     /* validate length */
1366     if (length < 0)
1367         HGOTO_ERROR(DFE_RANGE, FAIL);
1368 
1369     info = (compinfo_t *) access_rec->special_info;
1370 
1371     /* adjust length if it falls off the end of the element */
1372     if (length == 0)
1373         length = info->length - access_rec->posn;
1374     else if (length < 0 || access_rec->posn + length > info->length)
1375         HGOTO_ERROR(DFE_RANGE, FAIL);
1376 
1377     if ((*(info->minfo.model_funcs.read))(access_rec, length, data) == FAIL)
1378         HGOTO_ERROR(DFE_MODEL, FAIL);
1379 
1380     /* adjust access position */
1381     access_rec->posn += length;
1382 
1383     ret_value=length;
1384 
1385 done:
1386     if(ret_value == FAIL)
1387       { /* Error condition cleanup */
1388 
1389       } /* end if */
1390 
1391     /* Normal function cleanup */
1392     return ret_value;
1393 }   /* end HCPread() */
1394 
1395 /*--------------------------------------------------------------------------
1396  NAME
1397     HCPwrite -- Write out a portion of data from a compressed data element.
1398  USAGE
1399     int32 HCPwrite(access_rec,length,data)
1400     accrec_t *access_rec;   IN: the access record of the data element
1401     int32 length;           IN: the number of bytes to write
1402     void * data;             IN: the buffer to retrieve the bytes written
1403  RETURNS
1404     Returns the number of bytes written or FAIL
1405  DESCRIPTION
1406     Write out a number of bytes to a compressed data element.
1407 
1408  GLOBAL VARIABLES
1409  COMMENTS, BUGS, ASSUMPTIONS
1410  EXAMPLES
1411  REVISION LOG
1412 --------------------------------------------------------------------------*/
1413 int32
HCPwrite(accrec_t * access_rec,int32 length,const void * data)1414 HCPwrite(accrec_t * access_rec, int32 length, const void * data)
1415 {
1416     CONSTR(FUNC, "HCPwrite");   /* for HERROR */
1417     compinfo_t *info;           /* information on the special element */
1418     uint8       local_ptbuf[4];
1419     uint8       *p = local_ptbuf;  /* temp buffer ptr */
1420     filerec_t  *file_rec;           /* file record */
1421     int32       ret_value;
1422 
1423     /* convert file id to file record */
1424     file_rec = HAatom_object(access_rec->file_id);
1425 
1426     /* validate length */
1427     if (length < 0)
1428         HRETURN_ERROR(DFE_RANGE, FAIL);
1429 
1430     info = (compinfo_t *) access_rec->special_info;
1431     if ((*(info->minfo.model_funcs.write)) (access_rec, length, data) == FAIL)
1432         HGOTO_ERROR(DFE_MODEL, FAIL);
1433 
1434     /* update access record, and information about special element */
1435     access_rec->posn += length;
1436     if (access_rec->posn > info->length)
1437       {
1438           int32       data_off;        /* offset of the data we are checking */
1439 
1440           /* get the info for the dataset */
1441           if(HTPinquire(access_rec->ddid,NULL,NULL,&data_off,NULL)==FAIL)
1442               HGOTO_ERROR(DFE_INTERNAL, FAIL);
1443 
1444           info->length = access_rec->posn;
1445 
1446           INT32ENCODE(p, info->length);
1447           if (HPseek(file_rec, data_off + 4) == FAIL)
1448               HGOTO_ERROR(DFE_SEEKERROR, FAIL);
1449           /* re-write un-comp. len */
1450           if (HP_write(file_rec, local_ptbuf, 4) == FAIL)
1451               HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1452       }     /* end if */
1453 
1454     ret_value=length;  /* return length of bytes written */
1455 
1456 done:
1457     if(ret_value == FAIL)
1458       { /* Error condition cleanup */
1459 
1460       } /* end if */
1461 
1462     /* Normal function cleanup */
1463     return ret_value;
1464 }   /* end HCPwrite() */
1465 
1466 /*--------------------------------------------------------------------------
1467  NAME
1468     HCPinquire -- Inquire information about the access record and data element.
1469  USAGE
1470     int32 HCPinquire(access_rec,pfile_id,ptag,pref,plength,poffset,pposn,
1471                      paccess,pspecial)
1472     accrec_t *access_rec;   IN: the access record of the data element
1473     int32 *pfile_id;        OUT: ptr to file id
1474     uint16 *ptag;           OUT: ptr to tag of information
1475     uint16 *pref;           OUT: ptr to ref of information
1476     int32 *plength;         OUT: ptr to length of data element
1477     int32 *poffset;         OUT: ptr to offset of data element
1478     int32 *pposn;           OUT: ptr to position of access in element
1479     int16 *paccess;         OUT: ptr to access mode
1480     int16 *pspecial;        OUT: ptr to special code
1481  RETURNS
1482     Returns SUCCEED or FAIL
1483  DESCRIPTION
1484     Inquire information about the access record and data element.
1485 
1486  GLOBAL VARIABLES
1487  COMMENTS, BUGS, ASSUMPTIONS
1488  EXAMPLES
1489  REVISION LOG
1490 --------------------------------------------------------------------------*/
1491 int32
HCPinquire(accrec_t * access_rec,int32 * pfile_id,uint16 * ptag,uint16 * pref,int32 * plength,int32 * poffset,int32 * pposn,int16 * paccess,int16 * pspecial)1492 HCPinquire(accrec_t * access_rec, int32 *pfile_id, uint16 *ptag,
1493  uint16 *pref, int32 *plength, int32 *poffset, int32 *pposn, int16 *paccess,
1494            int16 *pspecial)
1495 {
1496     CONSTR(FUNC, "HCPinquire");   /* for HERROR */
1497     compinfo_t *info =          /* special information record */
1498         (compinfo_t *) access_rec->special_info;
1499     uint16 data_tag,data_ref;   /* tag/ref of the data we are checking */
1500     int32       data_off;        /* offset of the data we are checking */
1501 
1502     /* get the info for the dataset */
1503     if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,&data_off,NULL)==FAIL)
1504         HRETURN_ERROR(DFE_INTERNAL, FAIL);
1505 
1506     /* fill in the variables if they are present */
1507     if (pfile_id != NULL)
1508         *pfile_id = access_rec->file_id;
1509     if (ptag != NULL)
1510         *ptag = data_tag;
1511     if (pref != NULL)
1512         *pref = data_ref;
1513     if (plength != NULL)
1514         *plength = info->length;
1515     if (poffset != NULL)
1516         *poffset = data_off;
1517     if (pposn != NULL)
1518         *pposn = access_rec->posn;
1519     if (paccess != NULL)
1520         *paccess = (int16)access_rec->access;
1521     if (pspecial != NULL)
1522         *pspecial = (int16)access_rec->special;
1523 
1524     return (SUCCEED);
1525 }   /* end HCPinquire() */
1526 
1527 /*--------------------------------------------------------------------------
1528  NAME
1529     HCPendaccess -- Close the compressed data element and free the AID
1530  USAGE
1531     intn HCPendaccess(access_rec)
1532     accrec_t *access_rec;   IN: the access record of the data element
1533  RETURNS
1534     Returns SUCCEED or FAIL
1535  DESCRIPTION
1536     Close the compressed data element and free the AID.
1537 
1538  GLOBAL VARIABLES
1539  COMMENTS, BUGS, ASSUMPTIONS
1540  EXAMPLES
1541  REVISION LOG
1542 --------------------------------------------------------------------------*/
1543 intn
HCPendaccess(accrec_t * access_rec)1544 HCPendaccess(accrec_t * access_rec)
1545 {
1546     CONSTR(FUNC, "HCPendaccess");   /* for HERROR */
1547     filerec_t  *file_rec;           /* file record */
1548     intn      ret_value = SUCCEED;
1549 
1550     /* validate argument */
1551     if (access_rec == NULL)
1552         HGOTO_ERROR(DFE_ARGS, FAIL);
1553 
1554     /* convert file id to file record */
1555     file_rec = HAatom_object(access_rec->file_id);
1556     if (BADFREC(file_rec))
1557         HGOTO_ERROR(DFE_ARGS, FAIL);
1558 
1559     /* close the file pointed to by this access rec */
1560     if (HCPcloseAID(access_rec) == FAIL)
1561         HGOTO_ERROR(DFE_CANTCLOSE, FAIL);
1562 
1563     /* update file and access records */
1564     if (HTPendaccess(access_rec->ddid) == FAIL)
1565       HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1566 
1567     /* detach from the file */
1568     file_rec->attach--;
1569 
1570     /* free the access record */
1571     HIrelease_accrec_node(access_rec);
1572 
1573 done:
1574   if(ret_value == FAIL)
1575     { /* Error condition cleanup */
1576       if(access_rec!=NULL)
1577           HIrelease_accrec_node(access_rec);
1578     } /* end if */
1579 
1580   /* Normal function cleanup */
1581 
1582   return ret_value;
1583 }   /* end HCPendaccess() */
1584 
1585 /*--------------------------------------------------------------------------
1586  NAME
1587     HCPcloseAID -- Get rid of the compressed data element data structures
1588  USAGE
1589     int32 HCPcloseAID(access_rec)
1590     accrec_t *access_rec;   IN: the access record of the data element
1591  RETURNS
1592     Returns SUCCEED or FAIL
1593  DESCRIPTION
1594     Get rid of the compressed data element internal data structures
1595 
1596  GLOBAL VARIABLES
1597  COMMENTS, BUGS, ASSUMPTIONS
1598  EXAMPLES
1599  REVISION LOG
1600 --------------------------------------------------------------------------*/
1601 int32
HCPcloseAID(accrec_t * access_rec)1602 HCPcloseAID(accrec_t * access_rec)
1603 {
1604     CONSTR(FUNC, "HCPcloseAID");    /* for HERROR */
1605     compinfo_t *info;           /* special information record */
1606     int32       ret=SUCCEED;
1607 
1608     info = (compinfo_t *) access_rec->special_info;
1609     if ((ret = (*(info->minfo.model_funcs.endaccess)) (access_rec)) == FAIL)
1610         HRETURN_ERROR(DFE_MODEL, FAIL);
1611 
1612     /* Free the compression information */
1613     /* BMR - reset special_info to NULL after memory is freed; problem shown
1614        by the failure when running hdp list with a large file on PC - 12/6/98 */
1615     if (--(info->attached) == 0)
1616     {
1617        HDfree(info);
1618        access_rec->special_info = NULL;
1619     }
1620     return (ret);
1621 }   /* end HCPcloseAID() */
1622 
1623 /* ------------------------------- HCPinfo -------------------------------- */
1624 /*
1625 NAME
1626    HCPinfo -- return info about a compressed element
1627 USAGE
1628    int32 HCPinfo(access_rec, info_block)
1629    accrec_t        *  access_rec;   IN: access record of access element
1630    sp_info_block_t * info_block;   OUT: information about the special element
1631 RETURNS
1632    SUCCEED / FAIL
1633 DESCRIPTION
1634    Return information about the given compressed element.  Info_block is
1635    assumed to be non-NULL.
1636 
1637 ---------------------------------------------------------------------------*/
1638 int32
HCPinfo(accrec_t * access_rec,sp_info_block_t * info_block)1639 HCPinfo(accrec_t * access_rec, sp_info_block_t * info_block)
1640 {
1641     CONSTR(FUNC, "HCPinfo");
1642     compinfo_t *info =          /* special information record */
1643     (compinfo_t *) access_rec->special_info;
1644 
1645     /* validate access record */
1646     if (access_rec->special != SPECIAL_COMP)
1647         HRETURN_ERROR(DFE_INTERNAL, FAIL);
1648 
1649     /* fill in the info_block */
1650     info_block->key = SPECIAL_COMP;
1651 
1652     info_block->comp_type = (int32)info->cinfo.coder_type;
1653     info_block->model_type = (int32)info->minfo.model_type;
1654     info_block->comp_size = Hlength(access_rec->file_id, DFTAG_COMPRESSED, info->comp_ref);
1655 
1656     return SUCCEED;
1657 }   /* HCPinfo */
1658 
1659 /* ------------------------------- HCPgetinfo ----------------------------- */
1660 /*
1661 NAME
1662    HCget_config_info -- return info about configuration of a compression method
1663 
1664 USAGE
1665      intn HCget_config_info( comp_coder_t coder_type,
1666     uint32* compression_config_info)
1667         comp_coder_t coder_type;  IN: the compression type queried
1668     compression_config_info;  OUT: flags to indiat compression status
1669 
1670                 0 -- not enabled
1671         COMP_DECODER_ENABLED - decoding enabled
1672                 COMP_ENCODER_ENABLED - encoding enabled
1673 
1674 RETURNS
1675    SUCCEED / FAIL
1676 DESCRIPTION
1677    Return information about the given compresion method.
1678 
1679    Currently, reports if encoding and/or decoding are available. SZIP
1680    is the only method that varies in the current versions.
1681 
1682 
1683 ---------------------------------------------------------------------------*/
1684 intn
HCget_config_info(comp_coder_t coder_type,uint32 * compression_config_info)1685 HCget_config_info( comp_coder_t coder_type,  /* IN: compression type */
1686         uint32* compression_config_info)
1687 {
1688     CONSTR(FUNC, "HCget_config_info");
1689 
1690     *compression_config_info = 0;
1691     switch (coder_type)
1692       {
1693           case COMP_CODE_IMCOMP:    /* IMCOMP no longer supported */
1694                 *compression_config_info = 0;
1695               break;
1696           /* This block doesn't look intentional, for there is no "break;"
1697              before case COMP_CODE_RLE:, which means *compression_config_info
1698              was reassigned to something else even though it is "case
1699              COMP_CODE_NONE:"  When I added "break;" for "case COMP_CODE_NONE:",             some tests failed.  It needs to be checked out.-BMR, Jul 16, 2012*/
1700           case COMP_CODE_NONE:      /* "none" (i.e. no) encoding */
1701         *compression_config_info = 0;
1702           case COMP_CODE_RLE:   /* Run-length encoding */
1703           case COMP_CODE_NBIT:      /* N-bit encoding */
1704           case COMP_CODE_SKPHUFF:   /* Skipping Huffman encoding */
1705         *compression_config_info = COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED;
1706               break;
1707 
1708           case COMP_CODE_JPEG:  /* jpeg may be optional */
1709         *compression_config_info = COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED;
1710               break;
1711           case COMP_CODE_DEFLATE:   /* gzip 'deflate' encoding, maybe optional */
1712         *compression_config_info = COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED;
1713               break;
1714 
1715            case COMP_CODE_SZIP:
1716 #ifdef H4_HAVE_LIBSZ
1717         if (SZ_encoder_enabled()) {
1718         *compression_config_info = COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED;
1719         } else {
1720         *compression_config_info = COMP_DECODER_ENABLED;
1721         }
1722 #else
1723         *compression_config_info = 0;
1724 #endif /* H4_HAVE_LIBSZ */
1725               break;
1726           default:
1727         *compression_config_info = 0;
1728               HRETURN_ERROR(DFE_BADCODER, FAIL)
1729     }
1730     return SUCCEED;
1731 }
1732 
1733 /*--------------------------------------------------------------------------
1734  NAME
1735     HCPgetcomptype -- Retrieves compression type of an element
1736  USAGE
1737     intn HCPgetcomptype(aid, coder_type)
1738     int32 aid;                  IN: access record ID
1739     comp_coder_t* coder_type;   OUT: the type of compression
1740  RETURNS
1741     SUCCEED/FAIL
1742  DESCRIPTION
1743     This routine retrieves the compression type of the element, identified
1744     by 'aid'.  It is very similar to HCPgetcompinfo except that it only
1745     retrieves the compression type and not the compression information.  The
1746     routine is used by GRgetcomptype and SDgetcomptype.
1747 
1748  GLOBAL VARIABLES
1749  COMMENTS, BUGS, ASSUMPTIONS
1750  EXAMPLES
1751  REVISION LOG
1752     Dec. 2007: Added so that applications can get the compression method only.
1753         The immediate intention is to avoid the need for external
1754         libraries to be present when only compression type is desired
1755         and not compression information. -BMR
1756 --------------------------------------------------------------------------*/
1757 intn
HCPgetcomptype(int32 file_id,uint16 data_tag,uint16 data_ref,comp_coder_t * comp_type)1758 HCPgetcomptype(int32 file_id,
1759               uint16 data_tag, uint16 data_ref, /* IN: tag/ref of element */
1760               comp_coder_t* comp_type)  /* OUT: compression type */
1761 {
1762     CONSTR(FUNC, "HCPgetcomptype");    /* for HGOTO_ERROR */
1763     uint16      ctag, cref;    /* tag/ref for the special info header object */
1764     int32       data_id=FAIL;    /* temporary AID for header info */
1765     int32    temp_aid=FAIL;    /* temporary AID for header info */
1766     int32    data_len;    /* offset of the data we are checking */
1767     uint8      *p;        /* pointers to the temporary buffer */
1768     uint8      *local_ptbuf=NULL;    /* temporary buffer */
1769     uint16    sp_tag;        /* special tag */
1770     uint16    c_type;        /* compression type */
1771     filerec_t  *file_rec;    /* file record */
1772     intn        ret_value=SUCCEED;
1773 
1774     /* clear error stack */
1775     HEclear();
1776 
1777     /* convert file id to file rec and check for validity */
1778     file_rec = HAatom_object(file_id);
1779     if (BADFREC(file_rec))
1780         HGOTO_ERROR(DFE_ARGS, FAIL);
1781 
1782     /* get access element from dataset's tag/ref */
1783     if ((data_id=HTPselect(file_rec, data_tag, data_ref))!=FAIL)
1784     {
1785     /* get the info for the dataset */
1786     if(HTPinquire(data_id,&ctag,&cref,NULL,&data_len)==FAIL)
1787         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1788 
1789     /* if element is not special, return COMP_CODE_NONE */
1790     if (!SPECIALTAG(ctag))
1791     {
1792         *comp_type = COMP_CODE_NONE;
1793         HGOTO_DONE(SUCCEED);
1794     }
1795 
1796     /* element is special, proceed with reading special info header */
1797     if((local_ptbuf=(uint8 *)HDmalloc(data_len))==NULL)
1798         HGOTO_ERROR(DFE_NOSPACE, FAIL);
1799 
1800     /* Get the special info header */
1801     if ((temp_aid=Hstartaccess(file_id,MKSPECIALTAG(ctag),cref,DFACC_READ)) == FAIL)
1802         HGOTO_ERROR(DFE_BADAID, FAIL);
1803     if (Hread(temp_aid,2,local_ptbuf) == FAIL)
1804         HGOTO_ERROR(DFE_READERROR, FAIL);
1805 
1806     /* Get special tag */
1807     p = local_ptbuf;
1808     UINT16DECODE(p, sp_tag);
1809 
1810     /* If it is a compressed element, move forward until compression
1811     coder and get it */
1812     switch (sp_tag)
1813     {
1814     case SPECIAL_COMP:
1815         if (Hread(temp_aid,12,local_ptbuf) == FAIL)
1816         HGOTO_ERROR(DFE_READERROR, FAIL);
1817 
1818         /* Skip comp version, length, ref#, and model type */
1819         p = local_ptbuf + 2 + 4 + 2 + 2;
1820         UINT16DECODE(p, c_type);     /* get encoding type */
1821         *comp_type=(comp_coder_t)c_type;
1822         break;
1823 
1824     /* If element is chunked, hand over to the chunk interface to check
1825         if it is compressed and get the type */
1826     case SPECIAL_CHUNKED:
1827         if (HMCgetcomptype(temp_aid, comp_type)==FAIL)
1828         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1829         break;
1830 
1831     /* return COMP_CODE_NONE for a non-compressed element */
1832     /* Developer's Note: SPECIAL_COMPRAS may need special handling */
1833     case SPECIAL_LINKED:
1834     case SPECIAL_EXT:
1835     case SPECIAL_VLINKED:
1836     case SPECIAL_BUFFERED:
1837     case SPECIAL_COMPRAS:
1838     case 0:
1839         *comp_type = COMP_CODE_NONE;
1840         break;
1841 
1842     /* flag the error when special tag is not something valid */
1843     default:
1844         *comp_type = COMP_CODE_INVALID;
1845         HGOTO_ERROR(DFE_ARGS, FAIL);
1846     }
1847     }
1848     else /* no special element */
1849     {
1850         *comp_type = COMP_CODE_NONE;
1851     }
1852 
1853 done:
1854   if(ret_value == FAIL)
1855     { /* Error condition cleanup */
1856     } /* end if */
1857 
1858     /* end access to the aid's if they've been accessed */
1859     if (temp_aid != FAIL)
1860         if (Hendaccess(temp_aid)== FAIL)
1861             HERROR(DFE_CANTENDACCESS);
1862     if (data_id != FAIL)
1863         if (HTPendaccess(data_id)== FAIL)
1864             HERROR(DFE_CANTENDACCESS);
1865 
1866     /* release allocated memory */
1867     if (local_ptbuf != NULL)
1868         HDfree(local_ptbuf);
1869 
1870   /* Normal function cleanup */
1871   return ret_value;
1872 } /* HCPgetcomptype */
1873 
1874 
1875 /*--------------------------------------------------------------------------
1876  NAME
1877     HCPgetdatasize -- Retrieves the sizes of original and compressed data.
1878  USAGE
1879     int32 HCPgetdatasize(file_id, data_tag, data_ref, comp_size, orig_size)
1880         int32 file_id;        IN: file id
1881         uint16 data_tag;    IN: tag of the element
1882         uint16 data_ref;    IN: ref of element
1883         int32* comp_size;    OUT: size of compressed data
1884         int32* orig_size;    OUT: size of non-compressed data
1885  RETURNS
1886     SUCCEED/FAIL
1887  DESCRIPTION
1888     This routine gets access to the element pointed to by the dataset's
1889     tag/ref pair, then proceeds as followed:
1890     - If the element is not special, HCPgetdatasize will use Hlength to get
1891       the length of the data then return.
1892     - If the element is compressed, HCPgetdatasize will read the element's
1893       special header and decode it for the uncompressed data length and the
1894       compressed data ref#, then use Hlength to get the length of the
1895       compressed data.
1896     - If the element is chunked, HCPgetdatasize will let the chunking layer
1897       retrieve the sizes (HMCgetdatasize.)
1898  GLOBAL VARIABLES
1899  COMMENTS, BUGS, ASSUMPTIONS
1900  EXAMPLES
1901  REVISION LOG
1902 --------------------------------------------------------------------------*/
1903 intn
HCPgetdatasize(int32 file_id,uint16 data_tag,uint16 data_ref,int32 * comp_size,int32 * orig_size)1904 HCPgetdatasize(int32 file_id,
1905               uint16 data_tag, uint16 data_ref, /* IN: tag/ref of element */
1906               int32* comp_size,    /* OUT  - size of compressed data */
1907               int32* orig_size)    /* OUT  - size of non-compressed data */
1908 {
1909     CONSTR(FUNC, "HCPgetdatasize");    /* for HGOTO_ERROR */
1910     uint8      *local_ptbuf=NULL, *p;
1911     uint16    sp_tag;        /* special tag */
1912     uint16 comp_ref = 0;
1913     atom_t      data_id = FAIL;    /* dd ID of existing regular element */
1914     int32 len = 0;
1915     filerec_t  *file_rec;    /* file record */
1916     intn        ret_value=SUCCEED;
1917 
1918     /* clear error stack */
1919     HEclear();
1920 
1921     /* convert file id to file rec and check for validity */
1922     file_rec = HAatom_object(file_id);
1923     if (BADFREC(file_rec))
1924     HGOTO_ERROR(DFE_ARGS, FAIL);
1925 
1926     /* get access element from dataset's tag/ref */
1927     if ((data_id=HTPselect(file_rec, data_tag, data_ref))!=FAIL)
1928     {
1929     /* if the element is not special, that means dataset's tag/ref
1930     specifies the actual data that was written to the dataset, so
1931     we don't need to check further */
1932     if (HTPis_special(data_id)==FALSE)
1933         {
1934         if ((len = Hlength(file_id, data_tag, data_ref)) == FAIL)
1935         HGOTO_ERROR(DFE_BADLEN, FAIL);
1936         *orig_size = *comp_size = len;
1937         }
1938 
1939     /* if the element is special, get the special info header and decode
1940     for the uncompressed data length and the compressed data ref#, which
1941     will be used with DFTAG_COMPRESSED to get the compressed data len */
1942     else
1943     {
1944         int32 rec_len=0;
1945 
1946         /* Get the compression header (description record) */
1947         rec_len = HPread_drec(file_id, data_id, &local_ptbuf);
1948         if (rec_len <= 0)
1949         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1950 
1951         /* get special tag */
1952         p = local_ptbuf;
1953         INT16DECODE(p, sp_tag);
1954 
1955         /* verify that it is a compressed element, then get the data len */
1956         if (sp_tag == SPECIAL_COMP)
1957         {
1958         /* skip 2byte header_version */
1959         p = p + 2;
1960         INT32DECODE(p, len);    /* get _uncompressed_ data length */
1961         *orig_size = len;    /* set original data size */
1962 
1963         /* if no data written, set compressed data size too */
1964         if (len == 0)
1965         {
1966             *comp_size = len;
1967         }
1968         /* Data has been written, get compressed data size */
1969         else
1970         {
1971             /* get ref# of compressed data */
1972             UINT16DECODE(p, comp_ref);
1973             if ((len = Hlength(file_id, DFTAG_COMPRESSED, comp_ref)) == FAIL)
1974             HGOTO_ERROR(DFE_BADLEN, FAIL);
1975             *comp_size = len;    /* set compressed data size */
1976         } /* data written */
1977         } /* element is compressed */
1978 
1979         /* if it is a chunked element, hand the task over to the chunking
1980         layer. */
1981         else if (sp_tag == SPECIAL_CHUNKED)
1982         {
1983         if (HMCgetdatasize(file_id, p, comp_size, orig_size)==FAIL)
1984         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1985         }
1986 
1987         /* unlimited dimension and external data fall in here */
1988         else if (sp_tag == SPECIAL_LINKED || sp_tag == SPECIAL_EXT)
1989         {
1990         INT32DECODE(p, len);    /* get total data length */
1991         *orig_size = *comp_size = len;    /* set data sizes */
1992         }
1993     } /* else, data_id is special */
1994 
1995     /* end access to the aid */
1996     if (HTPendaccess(data_id) == FAIL)
1997         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1998     }  /* end if data_id != FAIL */
1999 
2000     else /* HTPselect failed */
2001         HGOTO_ERROR(DFE_CANTACCESS, FAIL);
2002 
2003 done:
2004     if(ret_value == FAIL)
2005     { /* Error condition cleanup */
2006     } /* end if */
2007 
2008     /* Normal function cleanup */
2009     if (local_ptbuf != NULL)
2010     HDfree(local_ptbuf);
2011 
2012     return ret_value;
2013 } /* HCPgetdatasize */
2014