Commit 7926ed06 authored by Uwe Schulzweida's avatar Uwe Schulzweida
Browse files

patch 0001-added-tile-support-to-the-iterator-interface

parent b054fa1c
......@@ -411,6 +411,8 @@ char *cdiIterator_inqVTime(CdiIterator *me); //Returns the validity date as
int cdiIterator_inqLevelType(CdiIterator *me, int levelSelector, char **outName_optional, char **outLongName_optional, char **outStdName_optional, char **outUnit_optional); //callers are responsible to Free() strings that they request
int cdiIterator_inqLevel(CdiIterator *me, int levelSelector, double *outValue1_optional, double *outValue2_optional); //outValue2 is only written to if the level is a hybrid level
int cdiIterator_inqLevelUuid(CdiIterator *me, int *outVgridNumber_optional, int *outLevelCount_optional, unsigned char outUuid_optional[CDI_UUID_SIZE]); //outUuid must point to a buffer of 16 bytes, returns an error code if no generalized zaxis is used.
int cdiIterator_inqTile(CdiIterator *me, int *outTileIndex, int *outTileAttribute); //Returns CDI_EINVAL if there is no tile information connected to the current field, *outTileIndex and *outTileAttribute will be set to -1 in this case.
int cdiIterator_inqTileCount(CdiIterator *me, int *outTileCount, int *outTileAttributeCount); //outTileAttributeCount is the count for the tile associated with the current field, a total attribute count cannot be inquired. Returns CDI_EINVAL if there is no tile information connected to the current field, *outTileCount and *outTileAttributeCount will be set to 0 in this case.
CdiParam cdiIterator_inqParam(CdiIterator *me);
int cdiIterator_inqDatatype(CdiIterator *me);
int cdiIterator_inqTsteptype(CdiIterator *me);
......@@ -1180,6 +1182,9 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion);
/* subtypeInqTile: Specialized version of subtypeInqSubEntry looking for tile/attribute pair. */
int subtypeInqTile(int subtypeID, int tileindex, int attribute);
/* subtypeInqAttribute: Inquire the value of a subtype attribute. Returns CDI_EINVAL if the attribute does not exist.*/
int subtypeInqAttribute(int subtypeID, int index, const char *key, int *outValue);
/* vlistInqVarSubtype: Return subtype ID for a given variable. */
int vlistInqVarSubtype(int vlistID, int varID);
......
......@@ -274,7 +274,8 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast
*outHaveForecastTime = false, *outHaveTimeRange = false;
return 0;
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 60: case 1000: case 1002: case 1100: case 40033:
//case 55 and case 40455 are the same: 55 is the proposed standard value, 40455 is the value in the local use range that is used by the dwd until the standard is updated.
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 60: case 1000: case 1002: case 1100: case 40033: case 40055:
*outHaveForecastTime = true, *outHaveTimeRange = false;
return 0;
......
......@@ -700,6 +700,105 @@ int cdiIterator_inqLevelUuid(CdiIterator* me, int* outVgridNumber, int* outLevel
}
}
/*
@Function cdiIterator_inqTile
@Title Inquire the tile information for the current field
@Prototype int cdiIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute)
@Parameter
@item iterator The iterator to operate on.
@item outTileIndex The index of the current tile, -1 if no tile information is available.
@item outTileAttribute The attribute of the current tile, -1 if no tile information is available.
@Result An error code. CDI_EINVAL if there is no tile information associated with the current field.
@Description
Inquire the tile index and attribute for the current field.
*/
int cdiIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute)
{
sanityCheck(me);
switch(me->filetype)
{
#ifdef HAVE_LIBGRIB_API
case FILETYPE_GRB:
case FILETYPE_GRB2:
return cdiGribIterator_inqTile(me, outTileIndex, outTileAttribute);
#endif
#ifdef HAVE_LIBNETCDF
case FILETYPE_NC:
case FILETYPE_NC2:
case FILETYPE_NC4:
case FILETYPE_NC4C:
#endif
#ifdef HAVE_LIBSERVICE
case FILETYPE_SRV:
#endif
#ifdef HAVE_LIBEXTRA
case FILETYPE_EXT:
#endif
#ifdef HAVE_LIBIEG
case FILETYPE_IEG:
#endif
return cdiFallbackIterator_inqTile(me, outTileIndex, outTileAttribute);
default:
Error(kUnexpectedFileTypeMessage);
return CDI_ELIBNAVAIL;
}
}
/**
@Function cdiIterator_inqTileCount
@Title Inquire the tile count and tile attribute counts for the current field
@Prototype int cdiIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount)
@Parameter
@item iterator The iterator to operate on.
@item outTileCount The number of tiles used for this variable, zero if no tile information is available.
@item outTileAttributeCount The number of attributes available for the tile of this field, zero if no tile information is available.
Note: This is not the global attribute count, which would be impossible to infer without reading the entire file if it's a GRIB file.
@Result An error code. CDI_EINVAL if there is no tile information associated with the current field.
@Description
Inquire the tile count and tile attribute counts for the current field.
*/
int cdiIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount)
{
sanityCheck(me);
switch(me->filetype)
{
#ifdef HAVE_LIBGRIB_API
case FILETYPE_GRB:
case FILETYPE_GRB2:
return cdiGribIterator_inqTileCount(me, outTileCount, outTileAttributeCount);
#endif
#ifdef HAVE_LIBNETCDF
case FILETYPE_NC:
case FILETYPE_NC2:
case FILETYPE_NC4:
case FILETYPE_NC4C:
#endif
#ifdef HAVE_LIBSERVICE
case FILETYPE_SRV:
#endif
#ifdef HAVE_LIBEXTRA
case FILETYPE_EXT:
#endif
#ifdef HAVE_LIBIEG
case FILETYPE_IEG:
#endif
return cdiFallbackIterator_inqTileCount(me, outTileCount, outTileAttributeCount);
default:
Error(kUnexpectedFileTypeMessage);
return CDI_ELIBNAVAIL;
}
}
/*
@Function cdiIterator_inqParam
@Title Get discipline, category, and number
......
......@@ -11,11 +11,12 @@
struct CdiFallbackIterator {
CdiIterator super;
int streamId, vlistId;
int streamId, vlistId, subtypeId;
char *path; //needed for clone() & serialize()
int variableCount, curVariable;
int curLevelCount, curLevel;
int curSubtypeCount, curSubtype;
int curTimestep;
};
......@@ -39,12 +40,15 @@ static CdiFallbackIterator *cdiFallbackIterator_condestruct(CdiFallbackIterator
if(me->vlistId == CDI_UNDEFID) goto closeStream;
me->variableCount = vlistNvars(me->vlistId);
if(me->variableCount <= 0) goto closeStream;
me->subtypeId = CDI_UNDEFID; //Will be set in cdiFallbackIterator_nextField()
me->curSubtypeCount = -1; //Will be set in cdiFallbackIterator_nextField()
me->curLevelCount = -1; //Will be set in cdiFallbackIterator_nextField()
//These values are chosen so that the natural increment at the start of cdiFallbackIterator_nextField() will correctly position us at the first slice.
me->curTimestep = 0;
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) goto closeStream;
me->curVariable = 0;
me->curSubtype = 0;
me->curLevel = -1;
me->path = strdup(path);
if(!me->path) goto closeStream;
......@@ -70,14 +74,20 @@ CdiIterator *cdiFallbackIterator_new(const char *path, int filetype)
return &cdiFallbackIterator_condestruct(NULL, path, filetype)->super;
}
//Fetches the info that is published by the variables in the base class from the current field.
static void fetchSuperInfo(CdiFallbackIterator *me)
//Fetches the info that is derived from the current variable. Most of this is published by the data members in the base class.
static void fetchVariableInfo(CdiFallbackIterator *me)
{
//Fetch data that's published via base class data members.
me->super.datatype = vlistInqVarDatatype(me->vlistId, me->curVariable);
me->super.timesteptype = vlistInqVarTsteptype(me->vlistId, me->curVariable);
me->super.gridId = vlistInqVarGrid(me->vlistId, me->curVariable);
int param = vlistInqVarParam(me->vlistId, me->curVariable);
cdiDecodeParam(param, &me->super.param.number, &me->super.param.category, &me->super.param.discipline);
//Fetch the current level and subtype counts.
me->curLevelCount = zaxisInqSize(vlistInqVarZaxis(me->vlistId, me->curVariable));
me->subtypeId = vlistInqVarSubtype(me->vlistId, me->curVariable);
me->curSubtypeCount = (me->subtypeId == CDI_UNDEFID) ? 1 : subtypeInqSize(me->subtypeId);
}
CdiFallbackIterator *cdiFallbackIterator_clone(CdiIterator *super)
......@@ -93,10 +103,12 @@ CdiFallbackIterator *cdiFallbackIterator_clone(CdiIterator *super)
clone->curVariable = me->curVariable;
clone->curLevelCount = me->curLevelCount;
clone->curLevel = me->curLevel;
clone->curSubtypeCount = me->curSubtypeCount;
clone->curSubtype = me->curSubtype;
clone->curTimestep = me->curTimestep;
clone->super.isAdvanced = super->isAdvanced;
if(super->isAdvanced) fetchSuperInfo(clone);
if(super->isAdvanced) fetchVariableInfo(clone);
return clone;
}
......@@ -107,8 +119,8 @@ char *cdiFallbackIterator_serialize(CdiIterator *super)
char *escapedPath = cdiEscapeSpaces(me->path);
char *result = (char *) Malloc(strlen(escapedPath)
+ 5 * (3 * sizeof (int) * CHAR_BIT / 8 + 1) + 1);
sprintf(result, "%s %d %d %d %d %d", escapedPath, me->variableCount, me->curVariable, me->curLevelCount, me->curLevel, me->curTimestep);
+ 7 * (3 * sizeof (int) * CHAR_BIT / 8 + 1) + 1);
sprintf(result, "%s %d %d %d %d %d %d %d", escapedPath, me->variableCount, me->curVariable, me->curLevelCount, me->curLevel, me->curSubtypeCount, me->curSubtype, me->curTimestep);
Free(escapedPath);
return result;
}
......@@ -142,11 +154,13 @@ CdiFallbackIterator *cdiFallbackIterator_deserialize(const char *description)
decodeValue(me->curVariable, description);
decodeValue(me->curLevelCount, description);
decodeValue(me->curLevel, description);
decodeValue(me->curSubtypeCount, description);
decodeValue(me->curSubtype, description);
decodeValue(me->curTimestep, description);
#undef decodeValue
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) goto closeStream;
if(me->super.isAdvanced) fetchSuperInfo(me);
if(me->super.isAdvanced) fetchVariableInfo(me);
return me;
......@@ -164,17 +178,22 @@ fail:
static int advance(CdiFallbackIterator *me)
{
me->curLevel++;
if(me->curLevel == me->curLevelCount)
if(me->curLevel >= me->curLevelCount)
{
me->curLevel = 0;
me->curSubtype++;
if(me->curSubtype >= me->curSubtypeCount)
{
me->curSubtype = 0;
me->curVariable++;
if(me->curVariable == me->variableCount)
if(me->curVariable >= me->variableCount)
{
me->curVariable = 0;
me->curTimestep++;
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) return CDI_EEOF;
}
}
}
return CDI_NOERR;
}
......@@ -184,11 +203,7 @@ int cdiFallbackIterator_nextField(CdiIterator *super)
int result = advance(me);
if(result) return result;
if(!me->curLevel)
{ //Fetch the information that may have changed (we are processing a new variable/timestep if this point is reached).
fetchSuperInfo(me);
me->curLevelCount = zaxisInqSize(vlistInqVarZaxis(me->vlistId, me->curVariable));
}
if(!me->curLevel && !me->curSubtype) fetchVariableInfo(me); //Check whether we are processing a new variable/timestep and fetch the information that may have changed in this case.
return CDI_NOERR;
}
......@@ -278,6 +293,32 @@ int cdiFallbackIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *
return CDI_NOERR;
}
int cdiFallbackIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
{
CdiFallbackIterator *me = (CdiFallbackIterator*)super;
if(!outTileIndex) outTileIndex = &(int){0};
if(!outTileAttribute) outTileAttribute = &(int){0};
int error = CDI_NOERR;
if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "tileIndex", outTileIndex)) error = CDI_EINVAL;
if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "tileAttribute", outTileAttribute)) error = CDI_EINVAL;
if(error) *outTileIndex = *outTileAttribute = -1; //Guarantee defined values in case of an error.
return error;
}
int cdiFallbackIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
{
CdiFallbackIterator *me = (CdiFallbackIterator*)super;
if(!outTileCount) outTileCount = &(int){0};
if(!outTileAttributeCount) outTileAttributeCount = &(int){0};
int error = CDI_NOERR;
if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "numberOfTiles", outTileCount)) error = CDI_EINVAL;
if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "numberOfTileAttributes", outTileAttributeCount)) error = CDI_EINVAL;
if(error) *outTileCount = *outTileAttributeCount = -1; //Guarantee defined values in case of an error.
return CDI_NOERR;
}
char *cdiFallbackIterator_copyVariableName(CdiIterator *super)
{
CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
......
......@@ -26,6 +26,8 @@ int cdiFallbackIterator_levelType(CdiIterator *me, int levelSelector, char **out
int cdiFallbackIterator_level(CdiIterator *me, int levelSelector, double *outValue1, double *outValue2);
int cdiFallbackIterator_zaxisUuid(CdiIterator *me, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE]);
char *cdiFallbackIterator_copyVariableName(CdiIterator *me);
int cdiFallbackIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute);
int cdiFallbackIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount);
void cdiFallbackIterator_readField(CdiIterator *me, double *buffer, size_t *nmiss);
void cdiFallbackIterator_readFieldF(CdiIterator *me, float *buffer, size_t *nmiss);
......
......@@ -21,14 +21,14 @@
struct CdiGribIterator {
CdiIterator super;
CdiInputFile* file;
CdiInputFile *file;
off_t fileOffset;
unsigned char* gribBuffer;
unsigned char *gribBuffer;
size_t bufferSize, curRecordSize;
#ifdef HAVE_LIBGRIB_API
grib_handle* gribHandle;
grib_handle *gribHandle;
#else
void* gribHandle;
void *gribHandle;
#endif
};
......@@ -88,7 +88,7 @@ CdiGribIterator *cdiGribIterator_makeClone(CdiIterator *super)
CdiGribIterator *me = (CdiGribIterator*)super;
//Allocate memory and copy data. (operations that may fail)
CdiGribIterator* result = (struct CdiGribIterator *) Malloc(sizeof(*result));
CdiGribIterator *result = (struct CdiGribIterator *) Malloc(sizeof(*result));
if(!result) goto fail;
result->file = me->file;
......@@ -139,9 +139,9 @@ char *cdiGribIterator_serialize(CdiIterator *super)
{
CdiGribIterator *me = (CdiGribIterator*)super;
const char* path = cdiInputFile_getPath(me->file);
char* escapedPath = cdiEscapeSpaces(path);
char* result = (char *) Malloc(strlen(escapedPath) + 3 * sizeof(int) * CHAR_BIT/8);
const char *path = cdiInputFile_getPath(me->file);
char *escapedPath = cdiEscapeSpaces(path);
char *result = (char *) Malloc(strlen(escapedPath) + 3 * sizeof(int) * CHAR_BIT/8);
sprintf(result, "%s %zu", escapedPath, me->fileOffset);
Free(escapedPath);
return result;
......@@ -150,8 +150,8 @@ char *cdiGribIterator_serialize(CdiIterator *super)
CdiGribIterator *cdiGribIterator_deserialize(const char *description)
{
char* path;
CdiGribIterator* me = (CdiGribIterator *) Malloc(sizeof(*me));
char *path;
CdiGribIterator *me = (CdiGribIterator *) Malloc(sizeof(*me));
if(!me) goto fail;
description = baseIter_constructFromString(&me->super, description);
......@@ -254,13 +254,13 @@ static ssize_t scanToGribMarker(CdiGribIterator *me)
static unsigned decode24(void *beData)
{
unsigned char* bytes = (unsigned char *)beData;
unsigned char *bytes = (unsigned char *)beData;
return ((unsigned)bytes[0] << 16) + ((unsigned)bytes[1] << 8) + (unsigned)bytes[2];
}
static uint64_t decode64(void *beData)
{
unsigned char* bytes = (unsigned char *)beData;
unsigned char *bytes = (unsigned char *)beData;
uint64_t result = 0;
for(size_t i = 0; i < 8; i++) result = (result << 8) + bytes[i];
return result;
......@@ -525,6 +525,46 @@ int cdiGribIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *outL
return CDI_NOERR;
}
int cdiGribIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
{
CdiGribIterator *me = (CdiGribIterator*)super;
int trash;
if(!outTileIndex) outTileIndex = &trash;
if(!outTileAttribute) outTileAttribute = &trash;
//Get the values if possible.
int error = CDI_NOERR;
long value;
if(grib_get_long(me->gribHandle, "tileIndex", &value)) error = CDI_EINVAL;
*outTileIndex = (int)value;
if(grib_get_long(me->gribHandle, "tileAttribute", &value)) error = CDI_EINVAL;
*outTileAttribute = (int)value;
//Ensure defined return values in case of failure.
if(error) *outTileIndex = *outTileAttribute = -1;
return error;
}
int cdiGribIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
{
CdiGribIterator *me = (CdiGribIterator*)super;
int trash;
if(!outTileCount) outTileCount = &trash;
if(!outTileAttributeCount) outTileAttributeCount = &trash;
//Get the values if possible.
int error = CDI_NOERR;
long value;
if(grib_get_long(me->gribHandle, "numberOfTiles", &value)) error = CDI_EINVAL;
*outTileCount = (int)value;
if(grib_get_long(me->gribHandle, "numberOfTileAttributes", &value)) error = CDI_EINVAL;
*outTileAttributeCount = (int)value;
//Ensure defined return values in case of failure.
if(error) *outTileCount = *outTileAttributeCount = 0;
return error;
}
char *cdiGribIterator_copyVariableName(CdiIterator *super)
{
CdiGribIterator *me = (CdiGribIterator*)super;
......@@ -549,7 +589,7 @@ void cdiGribIterator_readFieldF(CdiIterator *super, float *buffer, size_t *nmiss
CdiGribIterator *me = (CdiGribIterator*)super;
size_t valueCount = gribGetArraySize(me->gribHandle, "values");
double* temp = (double *) Malloc(valueCount*sizeof(*temp));
double *temp = (double *) Malloc(valueCount*sizeof(*temp));
cdiGribIterator_readField(super, temp, nmiss);
for(size_t i = valueCount; i--; ) buffer[i] = (float)temp[i];
Free(temp);
......
......@@ -29,6 +29,8 @@ char *cdiGribIterator_inqTime(CdiIterator *me, bool getEndTime);
int cdiGribIterator_levelType(CdiIterator *me, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit);
int cdiGribIterator_level(CdiIterator *me, int levelSelector, double *outValue1, double *outValue2);
int cdiGribIterator_zaxisUuid(CdiIterator *me, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE]);
int cdiGribIterator_inqTile(CdiIterator *me, int *outTileIndex, int *outTileAttribute);
int cdiGribIterator_inqTileCount(CdiIterator *me, int *outTileCount, int *outTileAttributeCount);
char *cdiGribIterator_copyVariableName(CdiIterator *me);
void cdiGribIterator_readField(CdiIterator *me, double *buffer, size_t *nmiss);
......
......@@ -273,6 +273,8 @@ module mo_cdi
public :: cdiIterator_inqLevelType
public :: cdiIterator_inqLevel
public :: cdiIterator_inqLevelUuid
public :: cdiIterator_inqTile
public :: cdiIterator_inqTileCount
public :: cdiIterator_inqParam
public :: cdiIterator_inqDatatype
public :: cdiIterator_inqTsteptype
......@@ -627,6 +629,7 @@ module mo_cdi
public :: subtypeInqActiveIndex
public :: subtypeDefActiveIndex
public :: subtypeInqTile
public :: subtypeInqAttribute
public :: vlistInqVarSubtype
public :: gribapiLibraryVersion
......@@ -3458,6 +3461,48 @@ contains
& outLevelCount_cptr, outUuid_cptr)
end function cdiIterator_inqLevelUuid
function cdiIterator_inqTile(me_dummy, outTileIndex_dummy,&
& outTileAttribute_dummy) result(f_result)
integer(c_int) :: f_result
type(t_CdiIterator), intent(in) :: me_dummy
integer(c_int), intent(inout) :: outTileIndex_dummy
integer(c_int), intent(inout) :: outTileAttribute_dummy
interface
function lib_cdiIterator_inqTile(me_dummy, outTileIndex_dummy,&
& outTileAttribute_dummy) bind(c, name = 'cdiIterator_inqTile')&
& result(c_result)
import c_int, c_ptr
integer(c_int) :: c_result
type(c_ptr), value :: me_dummy
integer(c_int), intent(inout) :: outTileIndex_dummy
integer(c_int), intent(inout) :: outTileAttribute_dummy
end function lib_cdiIterator_inqTile
end interface
f_result = lib_cdiIterator_inqTile(me_dummy%ptr, outTileIndex_dummy,&
& outTileAttribute_dummy)
end function cdiIterator_inqTile
function cdiIterator_inqTileCount(me_dummy, outTileCount_dummy,&
& outTileAttributeCount_dummy) result(f_result)
integer(c_int) :: f_result
type(t_CdiIterator), intent(in) :: me_dummy
integer(c_int), intent(inout) :: outTileCount_dummy
integer(c_int), intent(inout) :: outTileAttributeCount_dummy
interface
function lib_cdiIterator_inqTileCount(me_dummy, outTileCount_dummy,&
& outTileAttributeCount_dummy) bind(c, name = 'cdiIterator_inqTileCount')&
& result(c_result)
import c_int, c_ptr
integer(c_int) :: c_result
type(c_ptr), value :: me_dummy
integer(c_int), intent(inout) :: outTileCount_dummy
integer(c_int), intent(inout) :: outTileAttributeCount_dummy
end function lib_cdiIterator_inqTileCount
end interface
f_result = lib_cdiIterator_inqTileCount(me_dummy%ptr, outTileCount_dummy,&
& outTileAttributeCount_dummy)
end function cdiIterator_inqTileCount
function cdiIterator_inqParam(me_dummy) result(f_result)
type(t_CdiParam) :: f_result
type(t_CdiIterator), intent(in) :: me_dummy
......@@ -6236,4 +6281,32 @@ contains
end do
end subroutine streamInqHistoryString
function subtypeInqAttribute(subtypeID_dummy, index_dummy, key_dummy,&
& outValue_dummy) result(f_result)
integer(c_int) :: f_result
integer(c_int), value :: subtypeID_dummy
integer(c_int), value :: index_dummy
character(kind = c_char, len = *), intent(in) :: key_dummy
integer(c_int), intent(inout) :: outValue_dummy
character(kind = c_char) :: key_temp(len(key_dummy) + 1)
integer :: key_i
interface
function lib_subtypeInqAttribute(subtypeID_dummy, index_dummy, key_dummy,&
& outValue_dummy) bind(c, name = 'subtypeInqAttribute') result(c_result)
import c_char, c_int
integer(c_int) :: c_result
integer(c_int), value :: subtypeID_dummy
integer(c_int), value :: index_dummy
character(kind = c_char) :: key_dummy(*)
integer(c_int), intent(inout) :: outValue_dummy
end function lib_subtypeInqAttribute
end interface
do key_i = 1, len(key_dummy)
key_temp(key_i) = key_dummy(key_i:key_i)
end do
key_temp(len(key_dummy) + 1) = c_null_char
f_result = lib_subtypeInqAttribute(subtypeID_dummy, index_dummy, key_temp,&
& outValue_dummy)
end function subtypeInqAttribute
end module mo_cdi
......@@ -781,6 +781,41 @@ int subtypeInqTile(int subtypeID, int tileindex, int attribute)
keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], attribute)));
}
int subtypeInqAttribute(int subtypeID, int index, const char* key, int* outValue)
{
//Validate input params.
if(subtypeID == CDI_UNDEFID) xabort("CDI_UNDEFID was passed to %s() as a subtypeID. Please check the origin of that ID.", __func__);
subtype_t *subtype_ptr = reshGetVal(subtypeID, &subtypeOps);
if(!subtype_ptr) xabort("Internal error: subtypeID %d resolved to NULL.", subtypeID);
if((unsigned)index >= (unsigned)subtype_ptr->nentries)
{
xabort("index argument of %s() is out of range. Expected 0 <= index < %d, but got index = %d.", __func__, subtype_ptr->nentries, index);
}
if(!outValue) outValue = &(int){0};
if(!key) return CDI_EINVAL;
int iKey = attribute_to_index(key);
if(iKey < 0) return CDI_EINVAL;
//Find the entry.
struct subtype_entry_t* entry = subtype_ptr->entries;
for(; index--; entry = entry->next) if(!entry) xabort("internal error: preliminary end of subtype entry list");
//Find the attribute.
for(struct subtype_attr_t* attribute = entry->atts; attribute; attribute = attribute->next)
{
if(attribute->key == iKey)
{
*outValue = attribute->val;
return CDI_NOERR;
}
}
//Failed to find the attribute if this point is reached.
return CDI_EINVAL;
}
/* Construct a new subtype for a tile set. If a corresponding subtype
* already exists, then we return this subtype ID instead.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment