mirror of https://github.com/ecmwf/eccodes.git
136 lines
4.0 KiB
C++
136 lines
4.0 KiB
C++
/*
|
|
* (C) Copyright 2005- 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.
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* Jean Baptiste Filippi - 01.11.2005
|
|
***************************************************************************/
|
|
|
|
#include "grib_accessor.h"
|
|
#include <iostream>
|
|
|
|
// Note: A fast cut-down version of strcmp which does NOT return -1
|
|
// 0 means input strings are equal and 1 means not equal
|
|
GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
|
|
{
|
|
if (*a != *b)
|
|
return 1;
|
|
while ((*a != 0 && *b != 0) && *(a) == *(b)) {
|
|
a++;
|
|
b++;
|
|
}
|
|
return (*a == 0 && *b == 0) ? 0 : 1;
|
|
}
|
|
|
|
int grib_accessor::compare_accessors(grib_accessor* a2, int compare_flags)
|
|
{
|
|
int ret = 0;
|
|
long type1 = 0;
|
|
long type2 = 0;
|
|
int type_mismatch = 0;
|
|
grib_accessor_class* c1 = NULL;
|
|
grib_accessor* a1 = this;
|
|
|
|
if ((compare_flags & GRIB_COMPARE_NAMES) && grib_inline_strcmp(a1->name, a2->name))
|
|
return GRIB_NAME_MISMATCH;
|
|
|
|
if (compare_flags & GRIB_COMPARE_TYPES) {
|
|
type1 = a1->get_native_type();
|
|
type2 = a2->get_native_type();
|
|
|
|
type_mismatch = type1 != type2 ? 1 : 0;
|
|
}
|
|
|
|
// ret = GRIB_UNABLE_TO_COMPARE_ACCESSORS;
|
|
c1 = a1->cclass;
|
|
ret = c1->compare(a1, a2);
|
|
|
|
if (ret == GRIB_VALUE_MISMATCH && type_mismatch)
|
|
ret = GRIB_TYPE_AND_VALUE_MISMATCH;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int grib_accessor::add_attribute(grib_accessor* attr, int nest_if_clash)
|
|
{
|
|
int id = 0;
|
|
int idx = 0;
|
|
grib_accessor* pSame = NULL;
|
|
grib_accessor* pAloc = this;
|
|
|
|
if (this->has_attributes()) {
|
|
pSame = this->get_attribute_index(attr->name, &id);
|
|
}
|
|
|
|
if (pSame) {
|
|
if (nest_if_clash == 0)
|
|
return GRIB_ATTRIBUTE_CLASH;
|
|
pAloc = pSame;
|
|
}
|
|
|
|
for (id = 0; id < MAX_ACCESSOR_ATTRIBUTES; id++) {
|
|
if (pAloc->attributes[id] == NULL) {
|
|
// attr->parent=a->parent;
|
|
pAloc->attributes[id] = attr;
|
|
attr->parent_as_attribute = pAloc;
|
|
if (pAloc->same)
|
|
attr->same = pAloc->same->get_attribute_index(attr->name, &idx);
|
|
|
|
grib_context_log(this->context, GRIB_LOG_DEBUG, "added attribute %s->%s", this->name, attr->name);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
}
|
|
return GRIB_TOO_MANY_ATTRIBUTES;
|
|
}
|
|
|
|
grib_accessor* grib_accessor::get_attribute_index(const char* name, int* index)
|
|
{
|
|
int i = 0;
|
|
while (i < MAX_ACCESSOR_ATTRIBUTES && this->attributes[i]) {
|
|
if (!grib_inline_strcmp(this->attributes[i]->name, name)) {
|
|
*index = i;
|
|
return this->attributes[i];
|
|
}
|
|
i++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int grib_accessor::has_attributes()
|
|
{
|
|
return this->attributes[0] ? 1 : 0;
|
|
}
|
|
|
|
grib_accessor* grib_accessor::get_attribute(const char* name)
|
|
{
|
|
int index = 0;
|
|
const char* p = 0;
|
|
char* basename = NULL;
|
|
const char* attribute_name = NULL;
|
|
grib_accessor* acc = NULL;
|
|
p = name;
|
|
while (*(p + 1) != '\0' && (*p != '-' || *(p + 1) != '>'))
|
|
p++;
|
|
if (*(p + 1) == '\0') {
|
|
return this->get_attribute_index(name, &index);
|
|
}
|
|
else {
|
|
size_t size = p - name;
|
|
attribute_name = p + 2;
|
|
basename = (char*)grib_context_malloc_clear(this->context, size + 1);
|
|
basename = (char*)memcpy(basename, name, size);
|
|
acc = this->get_attribute_index(basename, &index);
|
|
grib_context_free(this->context, basename);
|
|
if (acc)
|
|
return acc->get_attribute(attribute_name);
|
|
else
|
|
return NULL;
|
|
}
|
|
}
|