9#include "../csources/glibwrapper.h"
10#include "../csources/r3types.h"
11#include "../csources/r3util.h"
12#include "../csources/inline.h"
42 strlcpy (str,
"In house", maxLen);
47static inline uint8_t
rdU8(
const uint8_t *p) {
return p[0]; }
48static inline uint16_t
rdU16BE(
const uint8_t *p){
return (uint16_t)((p[0]<<8)|p[1]); }
49static inline uint32_t
rdU32BE(
const uint8_t *p){
return (uint32_t)((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]); }
50static inline int32_t
rdI32BE(
const uint8_t *p){
return (int32_t)
rdU32BE(p); }
58 int16_t t2 = (int16_t)u;
60 int16_t sm = -(int16_t)(u & 0x7FFF);
63 if (sm >= -1000 && sm <= 1000)
return sm;
70 float f; memcpy(&f, &u,
sizeof(
float));
86 for(
int i=0;i<nbits;i++){
87 size_t byte = (br->
bitpos >> 3);
88 int offs = 7 - (int)(br->
bitpos & 7);
90 if(
byte >= br->
len)
return v;
91 uint8_t b = br->
buf[byte];
92 v = (v<<1) | ((b>>offs)&1u);
98static void debugPeekS7Integers(
const uint8_t *s7,
size_t s7Len,
int nbits,
int howMany){
99 if(!s7 || s7Len==0 || nbits<=0)
return;
101 fprintf(stderr,
"[S7] first %d raw ints (nbits=%d):", howMany, nbits);
102 for(
int i=0;i<howMany;i++){
103 uint32_t x =
bitGet(&br, nbits);
104 fprintf(stderr,
" %u", (
unsigned)x);
106 fprintf(stderr,
"\n");
112 if(cap==0){
return; }
113 if(!src){ dst[0]=0;
return; }
114 strncpy(dst, src, cap-1);
119 for(
size_t i=0;i<n;i++)
if(arr[i]==value)
return n;
120 if(n < maxN){ arr[n] = value;
return n+1; }
125 for(
size_t i=1;i<n;i++){
126 long key=a[i];
size_t j=i;
127 while(j>0 && a[j-1] > key){ a[j]=a[j-1]; j--; }
132static const uint8_t*
findNextGrib(
const uint8_t *p,
const uint8_t *end){
133 while(p + 16 <= end){
134 if(p[0]==
'G' && p[1]==
'R' && p[2]==
'I' && p[3]==
'B')
return p;
141 if (disc != 10)
return false;
142 if (!(cat==1 || cat==2 || cat==0))
return false;
146 case 2:
case 5:
case 192:
case 194:
147 if (isU) *isU =
true;
150 case 3:
case 6:
case 193:
case 195:
151 if (isU) *isU =
false;
153 default:
return false;
160 if(disc==0 && cat==2 &&
par==2)
return "10u";
161 if(disc==0 && cat==2 &&
par==3)
return "10v";
162 if(disc==0 && cat==2 &&
par==22)
return "gust";
163 if(disc==10 && cat==0 && (
par==3 ||
par==5 ||
par==8))
return "swh";
174 case 13:
return val / 3600;
175 case 0:
return val / 60;
177 case 10:
return val * 3;
178 case 11:
return val * 6;
179 case 12:
return val * 12;
180 case 2:
return val * 24;
181 case 3:
return val * 24 * 30;
182 case 4:
return val * 24 * 365;
188 if(h < 0)
return -1000000;
190 if(h <= 384) sc += 10;
else if(h <= 1000) sc += 5;
else sc -= 5;
193 if((h % 12)==0) sc++;
206 if(!pdt || pdtLen < 12)
return -1;
209 uint8_t unit = pdt[8];
210 int32_t val = (int32_t)((pdt[9]<<24)|(pdt[10]<<16)|(pdt[11]<<8)|pdt[12]);
216 uint8_t unit = pdt[18];
217 int32_t val = (int32_t)((pdt[19]<<24)|(pdt[20]<<16)|(pdt[21]<<8)|pdt[22]);
223 int best=-1, bestScore=-1000000;
224 int limit = (pdtLen > 64) ? 64 : (int)pdtLen;
225 for(
int uPos=0; uPos+5<=limit; uPos++){
226 uint8_t unit = pdt[uPos];
227 if(!(unit==0||unit==1||unit==2||unit==3||unit==4||unit==10||unit==11||unit==12||unit==13))
continue;
228 int32_t val = (int32_t)((pdt[uPos+1]<<24)|(pdt[uPos+2]<<16)|(pdt[uPos+3]<<8)|pdt[uPos+4]);
230 if(h < 0 || h > 384)
continue;
232 if(sc > bestScore || (sc==bestScore && (best<0 || h<best))){
233 bestScore = sc; best = h;
243 int refYear, refMonth,
refDay, refHour, refMinute, refSecond;
247 if(!s || bodyLen < 16 || !out)
return false;
272 if(!s || bodyLen < 9+58 || !out)
return false;
275 if(gdt != 0)
return false;
277 const uint8_t *g = s+9;
281 uint32_t basicAngle =
rdU32BE(g+24);
282 uint32_t subAngle =
rdU32BE(g+28);
284 int32_t la1i = (int32_t)
rdU32BE(g+32);
286 int32_t la2i = (int32_t)
rdU32BE(g+41);
291 int scan = (int)
rdU8(g+57);
293 if(Ni<=0 || Nj<=0)
return false;
294 if(DiU==0xFFFFFFFFu || DjU==0xFFFFFFFFu)
return false;
297 if(basicAngle!=0 && subAngle!=0 && subAngle!=0xFFFFFFFFu){
298 unit = (double)basicAngle / (
double)subAngle;
301 double lat1 = (double)la1i * unit;
302 double lon1 = (double)lo1u * unit;
303 double lat2 = (double)la2i * unit;
304 double lon2 = (double)lo2u * unit;
307 double diAbs = (double)DiU * unit;
308 double djAbs = (double)DjU * unit;
311 double dj = (lat2 >= lat1) ? djAbs : -djAbs;
314 double dLon = lon2 - lon1;
315 if (dLon > 180.0) dLon -= 360.0;
316 else if(dLon < -180.0) dLon += 360.0;
317 double di = (dLon >= 0.0) ? diAbs : -diAbs;
320 if(!(fabs(lat1) <= 90.0) && fabs(lat2) <= 90.0 && Nj>1){
321 lat1 = lat2 - (double)(Nj-1) * dj;
335static inline bool scanIPlus(
int scan){
return ( (scan & 0x80) == 0 ); }
336static inline bool scanJPlus(
int scan){
return ( (scan & 0x40) == 0 ); }
337static inline bool scanAdjI (
int scan){
return ( (scan & 0x20) == 0 ); }
338static inline bool scanBoustro(
int scan){
return ( (scan & 0x10) != 0 ); }
349 if(!s || bodyLen < 6 || !out)
return false;
372 if(!s || bodyLen < 5 || !out)
return false;
375 if(bodyLen < 16)
return false;
410 const uint8_t *
sec7; uint32_t sec7Len;
411 int haveS1, haveS3, haveS4, haveS5, haveS6, haveS7;
414static int bmBitAt(
const uint8_t *bm,
size_t bmBytes,
size_t k){
416 size_t byte = k >> 3;
417 if(
byte >= bmBytes)
return 1;
418 int bit = 7 - (int)(k & 7);
419 return ( (bm[
byte] >> bit) & 1u );
425 if(len < 16 || memcmp(buf,
"GRIB",4)!=0)
return -1;
426 if(buf[7] != 2)
return -1;
427 uint64_t totalLen =
rdU64BE(buf+8);
428 if(totalLen > len || totalLen < 16)
return -1;
430 MsgParse mp; memset(&mp, 0,
sizeof(mp));
433 while(off + 5 <= totalLen){
434 uint32_t sLen =
rdU32BE(buf+off);
435 if(sLen < 5 || off + sLen > totalLen)
break;
436 uint8_t sNum =
rdU8(buf+off+4);
437 const uint8_t *s = buf + off + 5;
438 uint32_t bodyLen = sLen - 5;
447 int disc = (int)
rdU8(buf+6);
454 if(bodyLen < 1)
return -1;
477 fprintf(stderr,
"[S3] GDT=3.0 Ni=%d Nj=%d lat1=%g lon1=%g di=%g dj=%g scan=0x%02X\n",
482 fprintf(stderr,
"[S5] var=%s drt=%d R=%g E=%d D=%d nbits=%d (sec7=%u bytes)\n",
490 if(!wantData) {
if(outValues) *outValues = NULL;
return 0; }
496 size_t nPts = (size_t)Ni * (
size_t)Nj;
498 float *vals = (
float*)malloc(nPts *
sizeof(
float));
507 const double twoE = ldexp(1.0, mp.
s5.
bScale);
508 const double dec = pow(10.0, -(
double)mp.
s5.
dScale);
511 float v = (float)(mp.
s5.
refV * dec);
512 for(
size_t k=0;k<nPts;k++){
513 vals[k] =
bmBitAt(bm, bmBytes, k) ? v : NAN;
516 for(
size_t k=0;k<nPts;k++){
519 double X = mp.
s5.
refV + (double)D * twoE;
520 vals[k] = (float)(X * dec);
527 else if(mp.
s5.
drt == 3){
529 const uint8_t *q = mp.
sec7;
530 size_t off7 = 0, nAvail = mp.
sec7Len;
531 for(
size_t k=0;k<nPts;k++){
533 if(off7 + 4 > nAvail){ free(vals);
return -1; }
546 if(outValues) *outValues = vals;
else free(vals);
561 while(d < -180.0) d += 360.0;
562 while(d >= 180.0) d -= 360.0;
584 if(!fileName || !
zone)
return false;
587 if(stat(fileName, &st) != 0){
588 fprintf(stderr,
"readGribLists: cannot stat %s\n", fileName);
591 FILE *f = fopen(fileName,
"rb");
593 fprintf(stderr,
"readGribLists: cannot open %s\n", fileName);
597 uint8_t *buf = (uint8_t*)malloc((
size_t)st.st_size);
598 if(!buf){ fclose(f); fprintf(stderr,
"readGribLists: malloc failed\n");
return false; }
599 if(fread(buf,1,(
size_t)st.st_size,f) != (
size_t)st.st_size){
600 fclose(f); free(buf); fprintf(stderr,
"readGribLists: short read\n");
return false;
608 const uint8_t *p = buf, *end = buf + st.st_size;
610 if(p + 16 > end)
break;
611 if(memcmp(p,
"GRIB",4)!=0 || p[7]!=2){ p++;
continue; }
613 int discipline = (int)
rdU8(p+6);
614 uint64_t totalLen =
rdU64BE(p+8);
615 if(totalLen < 16 || p + totalLen > end){
break; }
621 while(off + 5 <= totalLen){
622 uint32_t sLen =
rdU32BE(p+off);
623 if(sLen < 5 || off + sLen > totalLen)
break;
624 uint8_t sNum =
rdU8(p+off+4);
625 const uint8_t *s = p + off + 5;
626 uint32_t bodyLen = sLen - 5;
628 if(sNum == 1 && !haveS1){
630 }
else if(sNum == 4 && !haveS4){
631 haveS4 =
parseSec4(s, bodyLen, discipline, &s4);
634 if(haveS1 && haveS4)
break;
662 strcmp(sn,
"10u")==0 || strcmp(sn,
"10v")==0 ||
663 strcmp(sn,
"gust")==0 || strcmp(sn,
"swh")==0 ||
664 strcmp(sn,
"ucurr")==0 || strcmp(sn,
"vcurr")==0 ||
707 if(!fileName || !
zone)
return false;
710 if(stat(fileName, &st) != 0){ fprintf(stderr,
"readGribParameters: stat fail\n");
return false; }
712 FILE *f = fopen(fileName,
"rb");
713 if(!f){ fprintf(stderr,
"readGribParameters: open fail\n");
return false; }
716 if(fread(hdr,1,16,f)!=16){ fclose(f); fprintf(stderr,
"readGribParameters: short read\n");
return false; }
717 if(memcmp(hdr,
"GRIB",4)!=0 || hdr[7]!=2){ fclose(f); fprintf(stderr,
"readGribParameters: not GRIB2\n");
return false; }
718 uint64_t totalLen =
rdU64BE(hdr+8);
720 uint8_t *msg = (uint8_t*)malloc((
size_t)totalLen);
721 if(!msg){ fclose(f); fprintf(stderr,
"readGribParameters: malloc fail\n");
return false; }
723 if(fread(msg,1,(
size_t)totalLen,f)!=(
size_t)totalLen){ free(msg); fclose(f); fprintf(stderr,
"readGribParameters: short read 2\n");
return false; }
730 while(off + 5 <= totalLen){
731 uint32_t sLen =
rdU32BE(msg+off);
732 if(sLen < 5 || off + sLen > totalLen)
break;
733 uint8_t sNum =
rdU8(msg+off+4);
734 const uint8_t *s = msg + off + 5;
735 uint32_t bodyLen = sLen - 5;
737 if(sNum == 1 && !haveS1){
739 }
else if(sNum == 3 && !haveS3){
743 if(haveS1 && haveS3)
break;
751 if(!haveS3){ free(msg);
return false; }
758 double latStart = g3.
lat1;
759 double latEnd = g3.
lat1 + (g3.
Nj - 1) * g3.
dj;
760 double lonStart = g3.
lon1;
761 double lonEnd = g3.
lon1 + (g3.
Ni - 1) * g3.
di;
790 if(!fileName || !
zone)
return false;
798 fprintf(stderr,
"readGribAll: more than 1 dataDate not supported (n=%zu)\n",
zone->
nDataDate);
806 fprintf(stderr,
"readGribAll: calloc tGribData failed\n");
826 if(stat(fileName,&st)!=0){ fprintf(stderr,
"readGribAll: stat fail\n");
return false; }
827 FILE *f = fopen(fileName,
"rb");
828 if(!f){ fprintf(stderr,
"readGribAll: open fail\n");
return false; }
830 uint8_t *buf = (uint8_t*)malloc((
size_t)st.st_size);
831 if(!buf){ fclose(f); fprintf(stderr,
"readGribAll: malloc fail\n");
return false; }
832 if(fread(buf,1,(
size_t)st.st_size,f) != (
size_t)st.st_size){
833 fclose(f); free(buf); fprintf(stderr,
"readGribAll: short read\n");
return false;
837 const uint8_t *p = buf, *end = buf + st.st_size;
842 uint64_t totalLen =
rdU64BE(p+8);
843 if(totalLen < 16 || p + totalLen > end)
break;
844 int discipline = (int)
rdU8(p+6);
852 bool writeU = (strcmp(sn,
"10u")==0 || strcmp(sn,
"ucurr")==0);
853 bool writeV = (strcmp(sn,
"10v")==0 || strcmp(sn,
"vcurr")==0);
854 bool writeG = (strcmp(sn,
"gust")==0);
855 bool writeW = (strcmp(sn,
"swh")==0);
864 if(vals && iT>=0 && (writeU||writeV||writeG||writeW)){
866 const int Ni = mp.
s3.
Ni, Nj = mp.
s3.
Nj;
871 const bool iPlus = (di > 0);
872 const bool jPlus = (dj > 0);
880 int jStart = jPlus ? 0 : (Nj-1);
881 int jStep = jPlus ? 1 : -1;
883 for(
int jj=0; jj<Nj; jj++){
884 int j = jStart + jj*jStep;
886 bool thisIPlus = iPlus ^ (boust && ((jj & 1) != 0));
887 int iStart = thisIPlus ? 0 : (Ni-1);
888 int iStep = thisIPlus ? 1 : -1;
890 for(
int ii=0; ii<Ni; ii++){
891 int i = iStart + ii*iStep;
892 if(lin >= (
size_t)Ni*(size_t)Nj)
break;
894 double lat = lat1 + j * dj;
895 double lon = lon1 + i * di;
904 float v = vals[lin++];
906 long k =
idxTij(iT, (
int)iLon, (
int)iLat,
zone);
907 if (isnan (v)) v = 0.0f;
908 if (isCur && strcmp(sn,
"unknown")==0){
911 if (isnan (v)) v = 0.0f;
921 bool baseIPlus = iPlus;
922 int iStartBase = baseIPlus ? 0 : (Ni-1);
923 int iStepBase = baseIPlus ? 1 : -1;
925 for(
int ii=0; ii<Ni; ii++){
926 int i = iStartBase + ii*iStepBase;
928 bool thisJPlus = jPlus ^ (boust && ((ii & 1) != 0));
929 int jStart = thisJPlus ? 0 : (Nj-1);
930 int jStep = thisJPlus ? 1 : -1;
932 for(
int jj=0; jj<Nj; jj++){
933 int j = jStart + jj*jStep;
934 if(lin >= (
size_t)Ni*(size_t)Nj)
break;
936 double lat = lat1 + j * dj;
937 double lon = lon1 + i * di;
946 float v = vals[lin++];
948 long k =
idxTij(iT, (
int)iLon, (
int)iLat,
zone);
952 if(writeW)
tGribData[iFlow][k].
w = isnan(v) ? 0.0f : v;
static double lonCanonize(double lon)
return lon on ]-180, 180 ] interval
#define MAX_N_TIME_STAMPS
#define MAX_SIZE_SHORT_NAME
Zone zone
geographic zone covered by grib file
static uint32_t rdU32BE(const uint8_t *p)
static void bitInit(BitReader *br, const uint8_t *buf, size_t len)
static uint8_t rdU8(const uint8_t *p)
static void strCopySafe(char *dst, size_t cap, const char *src)
static bool scanJPlus(int scan)
static uint32_t bitGet(BitReader *br, int nbits)
static int32_t rdI32BE(const uint8_t *p)
char * gribReaderVersion(char *str, size_t maxLen)
return type of reader
static bool isCurrentTriplet(int disc, int cat, int par, bool *isU)
static uint64_t rdU64BE(const uint8_t *p)
static bool parseSec3LatLon(const uint8_t *s, uint32_t bodyLen, Sec3Grid *out)
static bool scanIPlus(int scan)
FlowP * tGribData[2]
grib data description
static long indLat(double lat, const Zone *zone)
static bool parseSec1(const uint8_t *s, uint32_t bodyLen, Sec1Info *out)
static bool parseSec4(const uint8_t *s, uint32_t bodyLen, int discipline, Sec4Info *out)
static int pdtLeadHours(int pdtn, const uint8_t *pdt, uint32_t pdtLen)
static int bmBitAt(const uint8_t *bm, size_t bmBytes, size_t k)
static bool parseSec5(const uint8_t *s, uint32_t bodyLen, Sec5Info *out)
static bool scanAdjI(int scan)
static uint16_t rdU16BE(const uint8_t *p)
static int unitToHours(uint8_t unit, int32_t val)
static int parseGrib2Message(const uint8_t *buf, size_t len, int wantData, MsgParse *out, float **outValues)
static int scoreHours(int h)
static const char * shortNameFor(int disc, int cat, int par)
static int findTimeIndex(long timeStep, const Zone *zone)
static int16_t readS16beFlexible(const uint8_t *p)
static const uint8_t * findNextGrib(const uint8_t *p, const uint8_t *end)
bool readGribLists(const char *fileName, Zone *zone)
Read lists zone.timeStamp, shortName, zone.dataDate, dataTime before full grib reading.
bool readGribAll(const char *fileName, Zone *zone, int iFlow)
read grib file using eccodes C API return true if OK
static bool scanBoustro(int scan)
bool readGribParameters(const char *fileName, Zone *zone)
Read grib parameters in zone before full grib reading.
static long idxTij(int iT, int iLon, int iLat, const Zone *zone)
static void sortLongAsc(long *a, size_t n)
static size_t updateLongUnique(long value, size_t n, size_t maxN, long arr[])
static long indLonWrap(double lon, const Zone *zone)
static float rdIEEE32BE(const uint8_t *p)
long dataTime[MAX_N_DATA_TIME]
char shortName[MAX_N_SHORT_NAME][MAX_SIZE_SHORT_NAME]
long timeStamp[MAX_N_TIME_STAMPS]
long dataDate[MAX_N_DATA_DATE]