1 /******************************************************************************
2  * $Id: gribdataset.h d23b5a0d22b88657e4fc31f2513701842f0b0585 2019-08-11 03:09:59 +0200 Even Rouault $
3  *
4  * Project:  GRIB Driver
5  * Purpose:  GDALDataset driver for GRIB translator for read support
6  * Author:   Bas Retsios, retsios@itc.nl
7  *
8  ******************************************************************************
9  * Copyright (c) 2007, ITC
10  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ******************************************************************************
30  *
31  */
32 
33 #ifndef GRIBDATASET_H
34 #define GRIBDATASET_H
35 
36 #include "cpl_port.h"
37 
38 #include <cerrno>
39 #include <cmath>
40 #include <cstddef>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #if HAVE_FCNTL_H
45 #  include <fcntl.h>
46 #endif
47 
48 #include <algorithm>
49 #include <memory>
50 #include <string>
51 
52 #include "cpl_conv.h"
53 #include "cpl_error.h"
54 #include "cpl_multiproc.h"
55 #include "cpl_string.h"
56 #include "cpl_vsi.h"
57 #include "degrib/degrib/degrib2.h"
58 #include "degrib/degrib/inventory.h"
59 #include "degrib/degrib/meta.h"
60 #include "degrib/degrib/myerror.h"
61 #include "degrib/degrib/type.h"
62 #include "gdal.h"
63 #include "gdal_frmts.h"
64 #include "gdal_pam.h"
65 #include "gdal_priv.h"
66 #include "ogr_spatialref.h"
67 
68 /************************************************************************/
69 /* ==================================================================== */
70 /*                              GRIBDataset                             */
71 /* ==================================================================== */
72 /************************************************************************/
73 
74 class GRIBArray;
75 class GRIBRasterBand;
76 
77 class GRIBDataset final: public GDALPamDataset
78 {
79     friend class GRIBArray;
80     friend class GRIBRasterBand;
81 
82   public:
83                 GRIBDataset();
84                 ~GRIBDataset();
85 
86     static GDALDataset *Open( GDALOpenInfo * );
87     static int          Identify( GDALOpenInfo * );
88     static GDALDataset *CreateCopy( const char * pszFilename,
89                                     GDALDataset *poSrcDS,
90                                     int bStrict, char ** papszOptions,
91                                     GDALProgressFunc pfnProgress,
92                                     void * pProgressData );
93 
94     CPLErr      GetGeoTransform( double *padfTransform ) override;
GetSpatialRef()95     const OGRSpatialReference* GetSpatialRef() const override {
96         return m_poSRS.get();
97     }
98 
GetRootGroup()99     std::shared_ptr<GDALGroup> GetRootGroup() const override { return m_poRootGroup; }
100 
101   private:
102     void SetGribMetaData(grib_MetaData *meta);
103     static GDALDataset *OpenMultiDim( GDALOpenInfo * );
104 
105     VSILFILE *fp;
106     // Calculate and store once as GetGeoTransform may be called multiple times.
107     double adfGeoTransform[6];
108 
109     GIntBig nCachedBytes;
110     GIntBig nCachedBytesThreshold;
111     int bCacheOnlyOneBand;
112     GRIBRasterBand *poLastUsedBand;
113     std::shared_ptr<GDALGroup> m_poRootGroup{};
114     std::shared_ptr<OGRSpatialReference> m_poSRS{};
115     std::unique_ptr<OGRSpatialReference> m_poLL{};
116     std::unique_ptr<OGRCoordinateTransformation> m_poCT{};
117 };
118 
119 /************************************************************************/
120 /* ==================================================================== */
121 /*                            GRIBRasterBand                             */
122 /* ==================================================================== */
123 /************************************************************************/
124 
125 class GRIBRasterBand final: public GDALPamRasterBand
126 {
127     friend class GRIBArray;
128     friend class GRIBDataset;
129 
130 public:
131     GRIBRasterBand( GRIBDataset *, int, inventoryType * );
132     virtual ~GRIBRasterBand();
133     virtual CPLErr IReadBlock( int, int, void * ) override;
134     virtual const char *GetDescription() const override;
135 
136     virtual double GetNoDataValue( int *pbSuccess = nullptr ) override;
137 
138     void    FindPDSTemplate();
139 
140     void    UncacheData();
141 
142     static void ReadGribData( VSILFILE *, vsi_l_offset, int, double **,
143                               grib_MetaData ** );
144 private:
145     CPLErr       LoadData();
146     void    FindNoDataGrib2(bool bSeekToStart = true);
147 
148     vsi_l_offset start;
149     int subgNum;
150     char *longFstLevel;
151 
152     double *m_Grib_Data;
153     grib_MetaData *m_Grib_MetaData;
154 
155     int nGribDataXSize;
156     int nGribDataYSize;
157     int     m_nGribVersion;
158 
159     bool    m_bHasLookedForNoData;
160     double  m_dfNoData;
161     bool    m_bHasNoData;
162 
163     int     m_nDisciplineCode = -1;
164     std::string m_osDisciplineName{};
165     int     m_nCenter = -1;
166     std::string m_osCenterName{};
167     int     m_nSubCenter = -1;
168     std::string m_osSubCenterName{};
169     std::string m_osSignRefTimeName{};
170     std::string m_osRefTime{};
171     std::string m_osProductionStatus{};
172     std::string m_osType{};
173     int     m_nPDTN = -1;
174     std::vector<GUInt32> m_anPDSTemplateAssembledValues{};
175 };
176 
177 namespace gdal {
178 namespace grib {
179 
180 // Thin layer to manage allocation and deallocation.
181 class InventoryWrapper {
182   public:
183 
InventoryWrapper(VSILFILE * fp)184     explicit InventoryWrapper(VSILFILE * fp)
185         : inv_(nullptr), inv_len_(0), num_messages_(0), result_(0) {
186       result_ = GRIB2Inventory(fp, &inv_, &inv_len_,
187                                0 /* all messages */, &num_messages_);
188     }
189 
~InventoryWrapper()190     ~InventoryWrapper() {
191         if (inv_ == nullptr) return;
192         for (uInt4 i = 0; i < inv_len_; i++) {
193             GRIB2InventoryFree(inv_ + i);
194         }
195         free(inv_);
196     }
197 
198     // Modifying the contents pointed to by the return is allowed.
get(int i)199     inventoryType * get(int i) const {
200       if (i < 0 || i >= static_cast<int>(inv_len_)) return nullptr;
201       return inv_ + i;
202     }
203 
length()204     uInt4 length() const { return inv_len_; }
num_messages()205     size_t num_messages() const { return num_messages_; }
result()206     int result() const { return result_; }
207 
208   private:
209     inventoryType *inv_;
210     uInt4 inv_len_;
211     int num_messages_;
212     int result_;
213 };
214 
215 }  // namespace grib
216 }  // namespace gdal
217 
218 const char* const apszJ2KDrivers[] =
219         { "JP2KAK", "JP2OPENJPEG", "JPEG2000", "JP2ECW" };
220 
221 #endif // GRIBDATASET_H
222