/src/gdal/frmts/grib/degrib/g2clib/aecunpack.c
Line | Count | Source |
1 | | #include <stdio.h> |
2 | | #include <stdlib.h> |
3 | | #include <limits.h> |
4 | | #include "grib2.h" |
5 | | |
6 | | #include "libaec.h" |
7 | | |
8 | | // Cf https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-42.shtml |
9 | | // and https://github.com/erget/wgrib2/commit/07b0f6fcb9669e0e3285318f50d516731b6956b2 |
10 | | |
11 | | g2int aecunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts, |
12 | | g2float *fld) |
13 | 16 | { |
14 | | |
15 | 16 | g2int iret = 0; |
16 | 16 | g2float refV; |
17 | | |
18 | 16 | rdieee(idrstmpl+0,&refV,1); |
19 | 16 | g2float bscale = (g2float)int_power(2.0,idrstmpl[1]); |
20 | 16 | g2float dscale = (g2float)int_power(10.0,-idrstmpl[2]); |
21 | 16 | g2float bdscale = bscale * dscale; |
22 | 16 | g2float refD = refV * dscale; |
23 | | |
24 | 16 | g2int nbits = idrstmpl[3]; |
25 | | // |
26 | | // if nbits equals 0, we have a constant field where the reference value |
27 | | // is the data value at each gridpoint |
28 | | // |
29 | 16 | if (nbits != 0) { |
30 | 16 | int nbytes_per_sample = (nbits + 7) / 8; |
31 | 16 | if( ndpts != 0 && nbytes_per_sample > INT_MAX / ndpts ) |
32 | 0 | { |
33 | 0 | return 1; |
34 | 0 | } |
35 | 16 | g2int* ifld=(g2int *)calloc(ndpts,sizeof(g2int)); |
36 | | // Was checked just before |
37 | | // coverity[integer_overflow,overflow_sink] |
38 | 16 | unsigned char* ctemp=(unsigned char *)calloc((size_t)(ndpts) * nbytes_per_sample,1); |
39 | 16 | if ( ifld == NULL || ctemp == NULL) { |
40 | 0 | fprintf(stderr, "Could not allocate space in aecunpack.\n" |
41 | 0 | "Data field NOT unpacked.\n"); |
42 | 0 | free(ifld); |
43 | 0 | free(ctemp); |
44 | 0 | return(1); |
45 | 0 | } |
46 | | |
47 | 16 | struct aec_stream strm = {0}; |
48 | 16 | strm.flags = idrstmpl[5]; // CCSDS compression options mask |
49 | 16 | strm.bits_per_sample = nbits; |
50 | 16 | strm.block_size = idrstmpl[6]; |
51 | 16 | strm.rsi = idrstmpl[7]; // Restart interval |
52 | | |
53 | 16 | strm.next_in = cpack; |
54 | 16 | strm.avail_in = len; |
55 | 16 | strm.next_out = ctemp; |
56 | 16 | strm.avail_out = (size_t)(ndpts) * nbytes_per_sample; |
57 | | |
58 | | // Note: libaec doesn't seem to be very robust to invalid inputs... |
59 | 16 | int status = aec_buffer_decode(&strm); |
60 | 16 | if (status != AEC_OK) |
61 | 12 | { |
62 | 12 | fprintf(stderr, "aec_buffer_decode() failed with return code %d", status); |
63 | 12 | iret = 1; |
64 | 12 | } |
65 | 4 | else |
66 | 4 | { |
67 | 4 | gbits(ctemp,ndpts * nbytes_per_sample,ifld,0,nbytes_per_sample*8,0,ndpts); |
68 | 4 | g2int j; |
69 | 1.62M | for (j=0;j<ndpts;j++) { |
70 | 1.62M | fld[j] = refD + bdscale*(g2float)(ifld[j]); |
71 | 1.62M | } |
72 | 4 | } |
73 | 16 | free(ctemp); |
74 | 16 | free(ifld); |
75 | 16 | } |
76 | 0 | else { |
77 | 0 | g2int j; |
78 | 0 | for (j=0;j<ndpts;j++) fld[j]=refD; |
79 | 0 | } |
80 | | |
81 | 16 | return(iret); |
82 | 16 | } |