diff --git a/INSTALL b/INSTALL old mode 100755 new mode 100644 index cfac07eb2..7d1c323be --- a/INSTALL +++ b/INSTALL @@ -1,40 +1,365 @@ +Installation Instructions +************************* -The grib_api installation is based on the standard configure utility. -It is tested on several platforms and with several compilers. However for some platforms -modifications to the installation engine may be required. If you encounter any problem -during the installation procedure please send an e-mail with your problem to -Software.Support@ecmwf.int. +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. -The only required package for a standard installation is jasper which enables the jpeg2000 -packing/unpacking algorithm. -It is possible to build grib_api without jasper, by using the --disable-jpeg configure option, -but to install a fully functional library, its download is recommended. + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. +Basic Installation +================== -Standard Installation + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options ===================== - 1. Download grib_api from https://software.ecmwf.int/wiki/display/GRIB/Releases. - 2. Unpack distribution: + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. - > gunzip grib_api-X.tar.gz - > tar xf grib_api-X.tar + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: - 3. Create the directory where to install grib_api say grib_api_dir + ./configure CC=c99 CFLAGS=-g LIBS=-lposix - > mkdir grib_api_dir + *Note Defining Variables::, for more details. - 4. Run the configure in the grib_api-X +Compiling For Multiple Architectures +==================================== - > cd grib_api-X - > ./configure --prefix=grib_api_dir + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. - 5. make, check and install + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. - > make - ... - > make check - ... - > make install - ... + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/definitions/bufr/section.3.def b/definitions/bufr/section.3.def index f2004c4e3..fbc14fd50 100644 --- a/definitions/bufr/section.3.def +++ b/definitions/bufr/section.3.def @@ -22,7 +22,7 @@ hash_array sequences (defaultSequence,"sequence.def",tablesMasterDir,tablesLocal position offsetSection3; section_length[3] section3Length ; unsigned[1] reserved = 0; -unsigned[2] numberOfDataSubsets : dump; +unsigned[2] numberOfSubsets : dump; if (section2Present && centre==98 && section2Length==52) { @@ -32,7 +32,7 @@ if (section2Present && centre==98 && section2Length==52) { 1 = {rdbType = 8; } 1 = {rdbType = 12; } } - if (isSatelliteType || numberOfDataSubsets>1) { + if (isSatelliteType || numberOfSubsets>1) { constant isSatellite=1; } else { constant isSatellite=0; @@ -44,7 +44,7 @@ if (section2Present && centre==98 && section2Length==52) { meta localLongitude2 bits(keyMore,0,26,-18000000,100000) : dump; meta localLatitude2 bits(keyMore,32,25,-9000000,100000) : dump; - if (numberOfDataSubsets>255 || + if (numberOfSubsets>255 || ( rdbSubtype>=121 && rdbSubtype <=130 ) || rdbSubtype==31) { meta ls.umberOfObservations bits(keySat,0,16) : dump,long_type; diff --git a/definitions/bufr/section.4.def b/definitions/bufr/section.4.def index ea5fb1bd7..02e30c567 100644 --- a/definitions/bufr/section.4.def +++ b/definitions/bufr/section.4.def @@ -18,15 +18,15 @@ meta selectGroupNumber bufr_group_number(); transient subsetNumber=0; if (compressedData) { meta numericValues bufr_data_array(offsetSection4,offsetBeforeData,offsetEndSection4,section4Length, - numberOfDataSubsets,subsetNumber,expandedCodes,expandedFlags, - stringValues,elementsDescriptorsIndex,compressedData) ; + numberOfSubsets,subsetNumber,expandedCodes,expandedFlags, + stringValues,elementsDescriptorsIndex,compressedData) : dump; } else { meta numericValues bufr_data_array(offsetSection4,offsetBeforeData,offsetEndSection4,section4Length, - numberOfDataSubsets,subsetNumber,expandedCodes,expandedFlags, - stringValues,elementsDescriptorsIndex,compressedData) ; + numberOfSubsets,subsetNumber,expandedCodes,expandedFlags, + stringValues,elementsDescriptorsIndex,compressedData) : dump; } -meta unpack unpack_bufr_values(numericValues); +meta unpack unpack_bufr_values(numericValues) ; section_padding section4Padding; position offsetEndSection4; diff --git a/src/grib_accessor_class_bufr_data_array.c b/src/grib_accessor_class_bufr_data_array.c index ccdeb8256..069940aad 100644 --- a/src/grib_accessor_class_bufr_data_array.c +++ b/src/grib_accessor_class_bufr_data_array.c @@ -29,7 +29,7 @@ MEMBERS = const char* offsetBeforeDataName MEMBERS = const char* offsetEndSection4Name MEMBERS = const char* section4LengthName - MEMBERS = const char* numberOfDataSubsetsName + MEMBERS = const char* numberOfSubsetsName MEMBERS = const char* subsetNumberName MEMBERS = const char* expandedDescriptorsName MEMBERS = const char* flagsName @@ -41,7 +41,7 @@ MEMBERS = grib_accessor* expandedAccessor MEMBERS = int* canBeMissing MEMBERS = long subsetNumber - MEMBERS = long numberOfDataSubsets + MEMBERS = long numberOfSubsets MEMBERS = long compressedData MEMBERS = grib_vdarray* numericValues MEMBERS = grib_vsarray* stringValues @@ -90,7 +90,7 @@ typedef struct grib_accessor_bufr_data_array { const char* offsetBeforeDataName; const char* offsetEndSection4Name; const char* section4LengthName; - const char* numberOfDataSubsetsName; + const char* numberOfSubsetsName; const char* subsetNumberName; const char* expandedDescriptorsName; const char* flagsName; @@ -102,7 +102,7 @@ typedef struct grib_accessor_bufr_data_array { grib_accessor* expandedAccessor; int* canBeMissing; long subsetNumber; - long numberOfDataSubsets; + long numberOfSubsets; long compressedData; grib_vdarray* numericValues; grib_vsarray* stringValues; @@ -227,7 +227,7 @@ static void init(grib_accessor* a,const long v, grib_arguments* params) self->offsetBeforeDataName = grib_arguments_get_name(a->parent->h,params,n++); self->offsetEndSection4Name = grib_arguments_get_name(a->parent->h,params,n++); self->section4LengthName = grib_arguments_get_name(a->parent->h,params,n++); - self->numberOfDataSubsetsName = grib_arguments_get_name(a->parent->h,params,n++); + self->numberOfSubsetsName = grib_arguments_get_name(a->parent->h,params,n++); self->subsetNumberName = grib_arguments_get_name(a->parent->h,params,n++); self->expandedDescriptorsName = grib_arguments_get_name(a->parent->h,params,n++); self->flagsName = grib_arguments_get_name(a->parent->h,params,n++); @@ -315,7 +315,7 @@ static int get_descriptors(grib_accessor* a) { for (i=0;icanBeMissing[i]=can_be_missing(self->expanded->v[i]->code); - ret=grib_get_long(h,self->numberOfDataSubsetsName,&(self->numberOfDataSubsets)); + ret=grib_get_long(h,self->numberOfSubsetsName,&(self->numberOfSubsets)); ret=grib_get_long(h,self->compressedDataName,&(self->compressedData)); ret=grib_get_long(h,self->subsetNumberName,&(self->subsetNumber)); @@ -339,7 +339,7 @@ static grib_sarray* decode_string_array(grib_context* c,unsigned char* data,long ret=grib_sarray_new(c,10,10); if (width) { grib_context_free(c,sval); - for (j=0;jnumberOfDataSubsets;j++) { + for (j=0;jnumberOfSubsets;j++) { sval=(char*)grib_context_malloc_clear(c,width+1); grib_decode_string(data,pos,width,sval); grib_sarray_push(c,ret,sval); @@ -368,7 +368,7 @@ static grib_darray* decode_double_array(grib_context* c,unsigned char* data,long localWidth=grib_decode_unsigned_long(data,pos,6); ret=grib_darray_new(c,100,100); if (localWidth) { - for (j=0;jnumberOfDataSubsets;j++) { + for (j=0;jnumberOfSubsets;j++) { lval=grib_decode_unsigned_long(data,pos,localWidth); if (grib_is_all_bits_one(lval,localWidth) && self->canBeMissing[i]) { dval=GRIB_MISSING_DOUBLE; @@ -436,12 +436,11 @@ static void decode_element(grib_context* c,grib_accessor_bufr_data_array* self, sar=decode_string_array(c,data,pos,i,self); grib_vsarray_push(c,self->stringValues,sar); index=grib_vsarray_used_size(self->stringValues); - dar=grib_darray_new(c,self->numberOfDataSubsets,10); + dar=grib_darray_new(c,self->numberOfSubsets,10); sar_size=grib_sarray_used_size(sar); - index=self->numberOfDataSubsets*(index-1); - for (ii=1;ii<=self->numberOfDataSubsets;ii++) { + index=self->numberOfSubsets*(index-1); + for (ii=1;ii<=self->numberOfSubsets;ii++) { x=(index+ii)*1000+self->expanded->v[i]->width/8; - /* x=index*1000+strlen(sar->v[idx]); */ grib_darray_push(c,dar,x); } grib_vdarray_push(c,self->numericValues,dar); @@ -568,9 +567,10 @@ static void push_zero_element(grib_accessor_bufr_data_array* self,grib_darray* d } } -/* static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide,long subset) { grib_accessor_bufr_data_array *self =(grib_accessor_bufr_data_array*)a; + int idx=0; + grib_section* section=0; grib_accessor* elementAccessor=NULL; grib_action creator = {0, }; creator.op = "bufr_data_element"; @@ -578,13 +578,22 @@ static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide, creator.flags = GRIB_ACCESSOR_FLAG_DUMP; creator.set = 0; - creator.name=self->expanded->v[self->elementsDescriptorsIndex->v[ide]]->name; - elementAccessor = grib_accessor_factory(section, &creator, 0, NULL); - accessor_bufr_data_element_set_index(elementAccessor,ide); - accessor_bufr_data_element_set_descriptors(elementAccessor,self->expanded); - accessor_bufr_data_element_set_numericValues(elementAccessor,self->numericValues); - accessor_bufr_data_element_set_stringValue(elementAccessor,self->stringValue); - accessor_bufr_data_element_set_compressedData(elementAccessor,self->compressedData); + idx = self->compressedData ? self->elementsDescriptorsIndex->v[0]->v[ide] : + self->elementsDescriptorsIndex->v[ide]->v[subset]; + + creator.name=self->expanded->v[idx]->shortName; + if (creator.name) { + section=a->sub_section; + elementAccessor = grib_accessor_factory(section, &creator, 0, NULL); + accessor_bufr_data_element_set_index(elementAccessor,ide); + accessor_bufr_data_element_set_descriptors(elementAccessor,self->expanded); + accessor_bufr_data_element_set_numericValues(elementAccessor,self->numericValues); + accessor_bufr_data_element_set_stringValues(elementAccessor,self->stringValues); + accessor_bufr_data_element_set_compressedData(elementAccessor,self->compressedData); + accessor_bufr_data_element_set_type(elementAccessor,self->expanded->v[idx]->type); + accessor_bufr_data_element_set_numberOfSubsets(elementAccessor,self->numberOfSubsets); + accessor_bufr_data_element_set_subsetNumber(elementAccessor,subset); + } return elementAccessor; } @@ -592,23 +601,23 @@ static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide, static int create_keys(grib_accessor* a) { grib_accessor_bufr_data_array *self =(grib_accessor_bufr_data_array*)a; int err=0; + grib_accessor* elementAccessor=0; long iss,end,elementsInSubset,ide; - grib_context* c=a->parent->h->context; + grib_section* section=a->sub_section; - end= self->compressedData ? 1 : self->numberOfDataSubsets; + end= self->compressedData ? 1 : self->numberOfSubsets; for (iss=0;isscompressedData ? grib_viarray_used_size(self->elementsDescriptorsIndex) : + elementsInSubset= self->compressedData ? grib_iarray_used_size(self->elementsDescriptorsIndex->v[0]) : grib_iarray_used_size(self->elementsDescriptorsIndex->v[iss]); for (ide=0;idesubsection->block); + elementAccessor=create_accessor_from_descriptor(a,ide,iss); + if (elementAccessor) grib_push_accessor(elementAccessor,section->block); } } return err; } -*/ #define MAX_NESTED_REPLICATIONS 8 @@ -662,7 +671,7 @@ static int decode_elements(grib_accessor* a) { if (self->elementsDescriptorsIndex) grib_viarray_delete(c,self->elementsDescriptorsIndex); self->elementsDescriptorsIndex=grib_viarray_new(c,100,100); - end= self->compressedData ? 1 : self->numberOfDataSubsets; + end= self->compressedData ? 1 : self->numberOfSubsets; numberOfDescriptors=grib_bufr_descriptors_array_used_size(self->expanded); @@ -837,7 +846,7 @@ static int decode_elements(grib_accessor* a) { } } - /* err=create_keys(a); */ + err=create_keys(a); return err; } @@ -863,9 +872,9 @@ static int value_count(grib_accessor* a,long* count) err=grib_get_long(a->parent->h,self->subsetNumberName,&subsetNumber); if (err) return err; - if (subsetNumber>self->numberOfDataSubsets) { + if (subsetNumber>self->numberOfSubsets) { err=GRIB_INVALID_KEY_VALUE; - grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfDataSubsetsName); + grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfSubsetsName); return err; } @@ -874,14 +883,14 @@ static int value_count(grib_accessor* a,long* count) *count=l; if (subsetNumber<=0) { - *count *= self->numberOfDataSubsets; + *count *= self->numberOfSubsets; } } else { if (subsetNumber>0) { *count=grib_iarray_used_size(self->elementsDescriptorsIndex->v[subsetNumber-1]); } else { *count=0; - for (i=0;inumberOfDataSubsets;i++) + for (i=0;inumberOfSubsets;i++) *count+=grib_iarray_used_size(self->elementsDescriptorsIndex->v[i]); } } @@ -904,11 +913,11 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len) { l=grib_vdarray_used_size(self->numericValues); err=grib_get_long(a->parent->h,self->subsetNumberName,&n); if (err) return err; - err=grib_get_long(a->parent->h,self->numberOfDataSubsetsName,&numberOfSubsets); + err=grib_get_long(a->parent->h,self->numberOfSubsetsName,&numberOfSubsets); if (err) return err; if (n>numberOfSubsets) { err=GRIB_INVALID_KEY_VALUE; - grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfDataSubsetsName); + grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfSubsetsName); return err; } diff --git a/src/grib_accessor_class_bufr_data_element.c b/src/grib_accessor_class_bufr_data_element.c index 40d7efa61..5d6bcbcae 100644 --- a/src/grib_accessor_class_bufr_data_element.c +++ b/src/grib_accessor_class_bufr_data_element.c @@ -26,6 +26,8 @@ MEMBERS = long index MEMBERS = int type MEMBERS = long compressedData + MEMBERS = long subsetNumber + MEMBERS = long numberOfSubsets MEMBERS = bufr_descriptors_array* descriptors MEMBERS = grib_vdarray* numericValues MEMBERS = grib_vsarray* stringValues @@ -63,6 +65,8 @@ typedef struct grib_accessor_bufr_data_element { long index; int type; long compressedData; + long subsetNumber; + long numberOfSubsets; bufr_descriptors_array* descriptors; grib_vdarray* numericValues; grib_vsarray* stringValues; @@ -157,6 +161,16 @@ void accessor_bufr_data_element_set_type(grib_accessor* a,int type) { self->type=type; } +void accessor_bufr_data_element_set_numberOfSubsets(grib_accessor* a,long numberOfSubsets) { + grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; + self->numberOfSubsets=numberOfSubsets; +} + +void accessor_bufr_data_element_set_subsetNumber(grib_accessor* a,long subsetNumber) { + grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; + self->subsetNumber=subsetNumber; +} + void accessor_bufr_data_element_set_compressedData(grib_accessor* a,int compressedData) { grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; self->compressedData=compressedData; @@ -184,9 +198,8 @@ void accessor_bufr_data_element_set_elementsDescriptorsIndex(grib_accessor* a,gr static void init(grib_accessor* a, const long len, grib_arguments* params) { - /* grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; */ a->length = 0; - /* a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY; */ + a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY; } static void dump(grib_accessor* a, grib_dumper* dumper) @@ -208,29 +221,89 @@ static void dump(grib_accessor* a, grib_dumper* dumper) static int unpack_string_array (grib_accessor* a, char** val, size_t *len) { - /* grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; */ + grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; - return GRIB_NOT_IMPLEMENTED; + int ret=0,i,idx; + long count=0; + grib_context* c=a->parent->h->context; + + value_count(a,&count); + + if (*lencompressedData) { + for (i=0;inumericValues->v[self->index]->v[i]/1000; + val[i]=grib_context_strdup(c,self->stringValues->v[idx]->v[i]); + } + } else { + idx=(int)self->numericValues->v[self->subsetNumber]->v[self->index]/1000; + val[0]=grib_context_strdup(c,self->stringValues->v[self->subsetNumber]->v[idx]); + } + + return ret; } static int unpack_string (grib_accessor* a, char* val, size_t *len) { - return GRIB_NOT_IMPLEMENTED; + sprintf(val,"test"); + return 0; } static int unpack_long (grib_accessor* a, long* val, size_t *len) { - return GRIB_NOT_IMPLEMENTED; + grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; + int ret=0,i; + long count=0; + + value_count(a,&count); + + if (*lencompressedData) { + for (i=0;inumericValues->v[self->index]->v[i]; + } + } else { + val[0]=(long)self->numericValues->v[self->subsetNumber]->v[self->index]; + } + + return ret; } static int unpack_double (grib_accessor* a, double* val, size_t *len) { - return GRIB_NOT_IMPLEMENTED; + grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; + int ret=0,i; + long count=0; + + value_count(a,&count); + + if (*lencompressedData) { + for (i=0;inumericValues->v[self->index]->v[i]; + } + } else { + val[0]=self->numericValues->v[self->subsetNumber]->v[self->index]; + } + + return ret; } static int value_count(grib_accessor* a,long* count) { - return 0; + int ret,size; + grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; + + if (!self->compressedData) return 1; + + size=grib_darray_used_size(self->numericValues->v[self->index]); + + ret= size == 1 ? 1 : self->numberOfSubsets; + + return ret; } static void destroy(grib_context* context,grib_accessor* a) @@ -239,15 +312,27 @@ static void destroy(grib_context* context,grib_accessor* a) static int get_native_type(grib_accessor* a){ grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; + int ret=GRIB_TYPE_DOUBLE; -/* - if (self->compressedData) { - - } else { + switch (self->type) { + case BUFR_DESCRIPTOR_TYPE_STRING: + ret=GRIB_TYPE_STRING; + break; + case BUFR_DESCRIPTOR_TYPE_DOUBLE: + ret=GRIB_TYPE_DOUBLE; + break; + case BUFR_DESCRIPTOR_TYPE_LONG: + ret=GRIB_TYPE_LONG; + break; + case BUFR_DESCRIPTOR_TYPE_TABLE: + ret=GRIB_TYPE_LONG; + break; + case BUFR_DESCRIPTOR_TYPE_FLAG: + ret=GRIB_TYPE_LONG; + break; } - */ - return self->type; + return ret; } diff --git a/src/grib_accessor_class_data_ccsds_packing.c b/src/grib_accessor_class_data_ccsds_packing.c index 484f3190a..15ad4ed56 100644 --- a/src/grib_accessor_class_data_ccsds_packing.c +++ b/src/grib_accessor_class_data_ccsds_packing.c @@ -48,7 +48,7 @@ or edit "accessor.class" and rerun ./make_class.pl static int pack_double(grib_accessor*, const double* val,size_t *len); static int unpack_double(grib_accessor*, double* val,size_t *len); -static int value_count(grib_accessor*, long*); +static int value_count(grib_accessor*,long*); static void init(grib_accessor*,const long, grib_arguments* ); static void init_class(grib_accessor_class*); @@ -93,7 +93,7 @@ static grib_accessor_class _grib_accessor_class_data_ccsds_packing = { 0, /* get native type */ 0, /* get sub_section */ 0, /* grib_pack procedures long */ - 0, /* grib_pack procedures long */ + 0, /* grib_pack procedures long */ 0, /* grib_pack procedures long */ 0, /* grib_unpack procedures long */ &pack_double, /* grib_pack procedures double */ @@ -136,6 +136,8 @@ static void init_class(grib_accessor_class* c) c->unpack_long = (*(c->super))->unpack_long; c->pack_string = (*(c->super))->pack_string; c->unpack_string = (*(c->super))->unpack_string; + c->pack_string_array = (*(c->super))->pack_string_array; + c->unpack_string_array = (*(c->super))->unpack_string_array; c->pack_bytes = (*(c->super))->pack_bytes; c->unpack_bytes = (*(c->super))->unpack_bytes; c->pack_expression = (*(c->super))->pack_expression; diff --git a/src/grib_accessor_class_unpack_bufr_values.c b/src/grib_accessor_class_unpack_bufr_values.c index dfec2f689..ecc79ca32 100644 --- a/src/grib_accessor_class_unpack_bufr_values.c +++ b/src/grib_accessor_class_unpack_bufr_values.c @@ -145,7 +145,7 @@ typedef struct grib_accessor_bufr_compressed_data { const char* offsetBeforeDataName; const char* offsetEndSection4Name; const char* section4LengthName; - const char* numberOfDataSubsetsName; + const char* numberOfSubsetsName; const char* subsetNumberName; const char* expandedDescriptorsName; const char* elementsName; @@ -169,7 +169,7 @@ typedef struct grib_accessor_bufr_compressed_data { long* scale; long* width; long numberOfElements; - long numberOfDataSubsets; + long numberOfSubsets; size_t numberOfDescriptors; double* values; int* is_constant; diff --git a/src/grib_api_internal.h b/src/grib_api_internal.h index a44652676..acf97a964 100644 --- a/src/grib_api_internal.h +++ b/src/grib_api_internal.h @@ -169,7 +169,7 @@ double rint(double x); #define GRIB_HANDLE_BIG_ECMWF_GRIB1 1 #define MAX_FILE_HANDLES_WITH_MULTI 10 -#define ACCESSORS_ARRAY_SIZE 2100 +#define ACCESSORS_ARRAY_SIZE 20000 #define MAX_NUM_CONCEPTS 2000 #define MAX_NUM_HASH_ARRAY 2000 diff --git a/src/grib_api_prototypes.h b/src/grib_api_prototypes.h index 37304d938..b671cbc65 100644 --- a/src/grib_api_prototypes.h +++ b/src/grib_api_prototypes.h @@ -253,6 +253,8 @@ size_t grib_viarray_used_size(grib_viarray *v); /* grib_accessor_class_bufr_data_element.c */ void accessor_bufr_data_element_set_index(grib_accessor *a, long index); void accessor_bufr_data_element_set_type(grib_accessor *a, int type); +void accessor_bufr_data_element_set_numberOfSubsets(grib_accessor *a, long numberOfSubsets); +void accessor_bufr_data_element_set_subsetNumber(grib_accessor *a, long subsetNumber); void accessor_bufr_data_element_set_compressedData(grib_accessor *a, int compressedData); void accessor_bufr_data_element_set_descriptors(grib_accessor *a, bufr_descriptors_array *descriptors); void accessor_bufr_data_element_set_numericValues(grib_accessor *a, grib_vdarray *numericValues); diff --git a/src/grib_nearest_class_lambert_conformal.c b/src/grib_nearest_class_lambert_conformal.c index d35efeacb..35fd47241 100644 --- a/src/grib_nearest_class_lambert_conformal.c +++ b/src/grib_nearest_class_lambert_conformal.c @@ -61,9 +61,9 @@ typedef struct grib_nearest_lambert_conformal{ double* lons; int lons_count; double* distances; - int* k; /* index */ - int* i; /* index into the lons array */ - int* j; /* index into the lats array */ + int* k; + int* i; + int* j; const char* Ni; const char* Nj; } grib_nearest_lambert_conformal; diff --git a/tests/bufr_dump.sh b/tests/bufr_dump.sh index ee65b7e9e..472050be4 100755 --- a/tests/bufr_dump.sh +++ b/tests/bufr_dump.sh @@ -9,6 +9,8 @@ # +set -ex + . ./include.sh REDIRECT=/dev/null diff --git a/tests/bufrdc_ref.sh b/tests/bufrdc_ref.sh index c593bf3b8..142f938ce 100755 --- a/tests/bufrdc_ref.sh +++ b/tests/bufrdc_ref.sh @@ -8,7 +8,7 @@ # virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. # -set -e +set -ex . ./include.sh diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 2d7bad428..1c24ceed8 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -10,7 +10,7 @@ ecbuild_add_library( TARGET grib_tools list( APPEND grib_tools_bins grib_keys grib_histogram grib_error grib_add big2gribex - grib_debug grib_info grib_filter grib_ls grib_dump + grib_debug grib_info grib_filter grib_ls grib_dump grib_merge grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair grib_packing grib_cmp grib_convert grib_distance grib_corruption_check grib_compare parser grib_count grib_index_build diff --git a/tools/Makefile.am b/tools/Makefile.am index 5c224933c..ea5b3ea22 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -14,7 +14,7 @@ libgrib_tools_la_SOURCES = grib_tools.c \ dist_bin_SCRIPTS = bufr_compare_dir bin_PROGRAMS = grib_keys grib_histogram grib_error grib_add big2gribex \ - grib_debug grib_info grib_filter grib_ls grib_dump \ + grib_debug grib_info grib_filter grib_ls grib_dump grib_merge \ grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair \ grib_packing grib_cmp grib_convert grib_distance grib_corruption_check\ grib_compare grib_list_keys parser grib_count grib_index_build grib1to2 \ @@ -32,6 +32,7 @@ noinst_PROGRAMS = gaussian grib_diff mars_request xref all_keys #compile #dumpl grib_corruption_check_SOURCES = grib_corruption_check.c grib_moments_SOURCES = grib_moments.c +grib_merge_SOURCES = grib_merge.c grib_to_netcdf_SOURCES = grib_to_netcdf.c grib_to_json_SOURCES = grib_to_json.c grib_dump_SOURCES = grib_dump.c diff --git a/tools/bufr_dump.c b/tools/bufr_dump.c index c4bc4d394..ac0556753 100644 --- a/tools/bufr_dump.c +++ b/tools/bufr_dump.c @@ -139,6 +139,7 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP); if (json) { + grib_set_long(h,"unpack",1); } else { sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length); if (!grib_options_on("C")) diff --git a/tools/grib_merge.c b/tools/grib_merge.c new file mode 100644 index 000000000..5b82fd1d2 --- /dev/null +++ b/tools/grib_merge.c @@ -0,0 +1,328 @@ +/* + * Copyright 2005-2012 ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + +/* + * C Implementation: grib_copy + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +#define MAX_KEY_VALUES 100 + +grib_handle *hh=0; +grib_values key_values[MAX_KEY_VALUES]; +int key_values_size=MAX_KEY_VALUES; + +char* grib_tool_description="Merge two fields with identical parameters and different geografical area"; +char* grib_tool_name="grib_merge"; +char* grib_tool_usage="[options] file file ... output_file"; + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value */ + {"f",0,0,0,1,0}, + {"c",0,0,1,0,0}, + {"r",0,0,0,1,0}, + {"q",0,0,1,0,0}, + {"p:",0,0,1,1,0}, + {"P:",0,0,0,1,0}, + {"B:",0,0,1,1,"md5Product"}, + {"V",0,0,0,1,0}, + {"W:",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"U",0,0,1,0,0}, + {"H",0,0,1,0,0}, + {"T:",0,0,1,0,"G"}, + {"S",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"7",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { + int ret=grib_tool(argc,argv); + return ret; +} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +inline int idx(double lat,double lon,double latFirst,double lonFirst,double latLast,double lonLast, + long Ni,double di,double dj) { + long ilon,ilat; + if ((ilon=(lon-lonFirst)/di) < 0 ) return -1; + if ((ilat=(latFirst-lat)/dj) < 0 ) return -1; + if (lon>lonLast) { + if (lonLast==180) { + lon-=360; + ilon=(lon-lonFirst)/di; + } else + return -1; + } + if (latcontext,GRIB_LOG_WARNING,"gridType=%s not supported",s2); + return NULL; + } + + len1=sizeof(s1)/sizeof(*s1); + err=grib_get_string(h1,"gridType",s1,&len1); + if (strcmp(s1,"regular_ll")) { + grib_context_log(h1->context,GRIB_LOG_WARNING,"gridType=%s not supported",s1); + return NULL; + } + + if (!grib_key_equal(h1,h2,"iDirectionIncrementInDegrees",GRIB_TYPE_DOUBLE,&err) ) { + grib_context_log(h1->context,GRIB_LOG_WARNING, + "unable to merge: different iDirectionIncrementInDegrees"); + return NULL; + } + if (!grib_key_equal(h1,h2,"jDirectionIncrementInDegrees",GRIB_TYPE_DOUBLE,&err) ) { + grib_context_log(h1->context,GRIB_LOG_WARNING, + "unable to merge: different jDirectionIncrementInDegrees"); + return NULL; + } + + grib_get_long(h1,"latitudeOfFirstGridPoint",&l1); + grib_get_long(h2,"latitudeOfFirstGridPoint",&l2); + grib_get_long(h2,"jDirectionIncrement",&idj); + if ( (l1-l2) % idj ) { + grib_context_log(h1->context,GRIB_LOG_WARNING, "unable to merge: incompatible grid"); + return NULL; + } + + grib_get_long(h1,"longitudeOfFirstGridPoint",&l1); + grib_get_long(h2,"longitudeOfFirstGridPoint",&l2); + grib_get_long(h2,"iDirectionIncrement",&idi); + if ( (l1-l2) % idi ) { + grib_context_log(h1->context,GRIB_LOG_WARNING, "unable to merge: incompatible grid"); + return NULL; + } + + /* yes we can!*/ + + /* do we have something to do?*/ + + if ( grib_key_equal(h1,h2,"latitudeOfFirstGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) && + grib_key_equal(h1,h2,"latitudeOfLastGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) && + grib_key_equal(h1,h2,"longitudeOfFirstGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) && + grib_key_equal(h1,h2,"longitudeOfLastGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) + ) { + /* no we don't */ + return NULL; + } + + /* yes we do! */ + + /* check scanning mode */ + grib_get_long(h1,"iScansNegatively",&iscan); + if (iscan) grib_set_long(h1,"swapScanningLon",1); + grib_get_long(h2,"iScansNegatively",&iscan); + if (iscan) grib_set_long(h2,"swapScanningLon",1); + + grib_get_long(h1,"jScansPositively",&jscan); + if (jscan) grib_set_long(h1,"swapScanningLat",1); + grib_get_long(h2,"jScansPositively",&jscan); + if (jscan) grib_set_long(h2,"swapScanningLat",1); + + grib_get_double(h1,"latitudeOfFirstGridPointInDegrees",&latFirst1); + grib_get_double(h2,"latitudeOfFirstGridPointInDegrees",&latFirst2); + grib_get_double(h1,"longitudeOfFirstGridPointInDegrees",&lonFirst1); + grib_get_double(h2,"longitudeOfFirstGridPointInDegrees",&lonFirst2); + + latFirst = latFirst1>latFirst2 ? latFirst1 : latFirst2; + lonFirst = lonFirst1lonLast2 ? lonLast1 : lonLast2; + + grib_get_double(h1,"iDirectionIncrementInDegrees",&di1); + grib_get_double(h1,"jDirectionIncrementInDegrees",&dj1); + grib_get_double(h2,"iDirectionIncrementInDegrees",&di2); + grib_get_double(h2,"jDirectionIncrementInDegrees",&dj2); + grib_get_double(h1,"iDirectionIncrementInDegrees",&di); + grib_get_double(h1,"jDirectionIncrementInDegrees",&dj); + grib_get_long(h1,"Ni",&Ni1); + grib_get_long(h1,"Nj",&Nj1); + grib_get_long(h2,"Ni",&Ni2); + grib_get_long(h2,"Nj",&Nj2); + + if (lonFirst==0 && lonLast==360) lonLast-=di; + if (lonFirst==-180 && lonLast==180) { + lonFirst=0; + lonLast=360-di; + } + + /* create new grib for bigger area*/ + h=grib_handle_clone(h1); + grib_set_double(h,"latitudeOfFirstGridPointInDegrees",latFirst); + grib_set_double(h,"longitudeOfFirstGridPointInDegrees",lonFirst); + grib_set_double(h,"latitudeOfLastGridPointInDegrees",latLast); + grib_set_double(h,"longitudeOfLastGridPointInDegrees",lonLast); + Ni=fabs(lonLast-lonFirst)/di+1; + Nj=fabs(latLast-latFirst)/dj+1; + + grib_set_long(h,"Ni",Ni); + grib_set_long(h,"Nj",Nj); + + grib_get_long(h,"bitmapPresent",&bitmapPresent); + if (!bitmapPresent) grib_set_long(h,"bitmapPresent",1); + + grib_get_long(h,"numberOfPoints",&n); + grib_get_double(h,"missingValue",&missingValue); + v=grib_context_malloc_clear(h->context,sizeof(double)*n); + for (i=0;icontext,sizeof(double)*n); + lon=grib_context_malloc_clear(h->context,sizeof(double)*n); + sn=n; + grib_get_double_array(h,"latitudes",lat,&sn); + grib_get_double_array(h,"longitudes",lon,&sn); + + grib_get_long(h1,"numberOfPoints",&n1); + v1=grib_context_malloc_clear(h->context,sizeof(double)*n1); + lat1=grib_context_malloc_clear(h->context,sizeof(double)*n1); + lon1=grib_context_malloc_clear(h->context,sizeof(double)*n1); + sn=n1; + grib_get_double_array(h1,"latitudes",lat1,&sn); + grib_get_double_array(h1,"longitudes",lon1,&sn); + grib_get_double_array(h1,"values",v1,&sn); + + grib_get_long(h2,"numberOfPoints",&n2); + v2=grib_context_malloc_clear(h->context,sizeof(double)*n2); + lat2=grib_context_malloc_clear(h->context,sizeof(double)*n2); + lon2=grib_context_malloc_clear(h->context,sizeof(double)*n2); + sn=n2; + grib_get_double_array(h2,"latitudes",lat2,&sn); + grib_get_double_array(h2,"longitudes",lon2,&sn); + grib_get_double_array(h2,"values",v2,&sn); + + for (i=0;i=0 ) { + v[i]=v1[j]; + } else if ( (j=idx(lat[i],lon[i],latFirst2,lonFirst2,latLast2,lonLast2,Ni2,di2,dj2))>=0) { + v[i]=v2[j]; + } + } + + grib_set_double_array(h,"values",v,n); + + return h; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + int err=0; + grib_handle* hm=0; + char md5[200]={0,}; + char fname[210]={0,}; + size_t lmd5; + + if (!hh) { hh=grib_handle_clone(h); return 0; } + grib_get_string(h,"md5Product",md5,&lmd5); + sprintf(fname,"_%s.orig.grib",md5); + grib_write_message(h,fname,"a"); + + if ((hm=merge(h,hh))==NULL ) { + grib_tools_write_message(options,hh); + lmd5=sizeof(md5)/sizeof(*md5); + grib_get_string(hh,"md5Product",md5,&lmd5); + sprintf(fname,"_%s.merge.grib",md5); + grib_write_message(hh,fname,"a"); + } + grib_handle_delete(hh); + hh = hm!=NULL ? hm : grib_handle_clone(h) ; + + return err; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + grib_tools_write_message(options,hh); + if (options->outfile->file) { + fclose(options->outfile->file); + } + return 0; +}