You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@etch.apache.org by jd...@apache.org on 2009/04/22 19:25:51 UTC
svn commit: r767594 [15/43] - in /incubator/etch/trunk/binding-c/runtime/c:
./ ext/ ext/hashtab/ ext/lib/ inc/ lib/ project/ project/$etchstop/
project/bin/ project/etch/ project/logcli/ project/logsrv/ project/notes/
project/test/ project/test/logcli/...
Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_out.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_out.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_out.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_out.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,157 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * etch_tagdata_out.c -- tagged_data_output base class default implementation.
+ */
+
+#include <stdio.h>
+#include "etch_tagdata_out.h"
+#include "etch_global.h"
+
+
+int tdo_start_message(tagged_data_output* tdo, etch_message* msg)
+{
+ return -1;
+}
+
+
+int tdo_write_message(tagged_data_output* tdo, etch_message* msg, etch_flexbuffer* fb)
+{
+ return -1;
+}
+
+
+
+int tdo_end_message(tagged_data_output* tdo, etch_message* msg)
+{
+ return NULL;
+}
+
+
+int tdo_start_struct(tagged_data_output* tdo, struct etch_structvalue* sv)
+{
+ return -1;
+}
+
+
+int tdo_write_struct(tagged_data_output* tdo, struct etch_structvalue* sv)
+{
+ return -1;
+}
+
+
+int tdo_end_struct(tagged_data_output* tdo, struct etch_structvalue* sv)
+{
+ return -1;
+}
+
+
+int tdo_start_array(tagged_data_output* tdo, etch_arrayvalue* x)
+{
+ return -1;
+}
+
+
+int tdo_write_array(tagged_data_output* tdo, etch_arrayvalue* x, etch_validator* v)
+{
+ return -1;
+}
+
+
+int tdo_end_array(tagged_data_output* tdo, etch_arrayvalue* x)
+{
+ return -1;
+}
+
+
+/**
+ * destroy_tagged_data_output()
+ */
+int destroy_tagged_data_output(tagged_data_output* tdo)
+{
+ if (tdo->refcount > 0 && --tdo->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(tdo))
+ if (tdo->impl)
+ tdo->impl->destroy(tdo->impl);
+
+ destroy_objectex((objmask*)tdo);
+ return 0;
+}
+
+
+/**
+ * clone_tagged_data_output()
+ */
+tagged_data_output* clone_tagged_data_output(tagged_data_output* tdo)
+{
+ tagged_data_output* newtdo = (tagged_data_output*) clone_object((objmask*) tdo);
+
+ if (tdo->impl)
+ newtdo->impl = tdo->impl->clone(tdo->impl);
+
+ return newtdo;
+}
+
+
+i_tagged_data_output* new_tdo_vtable()
+{
+ i_tagged_data_output* vtab
+ = new_vtable(NULL, sizeof(i_tagged_data_output), CLASSID_TDO_VTAB);
+
+ vtab->start_message = tdo_start_message;
+ vtab->write_message = tdo_write_message;
+ vtab->end_message = tdo_end_message;
+ vtab->start_struct = tdo_start_struct;
+ vtab->write_struct = tdo_write_struct;
+ vtab->end_struct = tdo_end_struct;
+ vtab->start_array = tdo_start_array;
+ vtab->write_array = tdo_write_array;
+ vtab->end_array = tdo_end_array;
+ return vtab;
+}
+
+
+/**
+ * new_tagged_data_output()
+ * tagged_data_output constructor
+ */
+tagged_data_output* new_tagged_data_output(const short objtype, const short class_id)
+{
+ i_tagged_data_output* vtab = NULL;
+
+ tagged_data_output* tdo = (tagged_data_output*) new_object
+ (sizeof(tagged_data_output), ETCHTYPEB_TAGDATAOUT, CLASSID_TAGDATAOUT);
+
+ tdo->destroy = destroy_tagged_data_output;
+ tdo->clone = clone_tagged_data_output;
+
+ vtab = cache_find(get_vtable_cachehkey(CLASSID_TDO_VTAB), 0);
+
+ if(!vtab)
+ {
+ vtab = new_tdo_vtable();
+ cache_insert(vtab->hashkey, vtab, FALSE);
+ }
+
+ tdo->vtab = vtab;
+ return tdo;
+}
+
+
Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_type.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_type.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_type.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_type.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,878 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * type.c -- methods on the etch_type object.
+ * type denotes the type of a struct or message. when used with a message
+ * it typically denotes an action or event. an etch_type is a typedef of
+ * etch_id_name, however it has additional instance data specific to type.
+ */
+
+#include "etch_type.h"
+#include "etch_syncobj.h"
+#include "etch_validator.h"
+#include "etch_global.h"
+#include "etchmap.h"
+#include "etchutl.h"
+
+int fieldmap_clear_handler (void* key, void* value);
+etch_hashtable* new_etchtype_fieldmap();
+etch_hashtable* new_etchtype_vtormap();
+int destroy_type_impl(etch_type_impl* impl);
+
+
+/* - - - - - - - - - - - - - - - - - -
+ * constructors and destructors
+ * - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * new_type()
+ * etch_type constructor
+ */
+etch_type* new_type(const wchar_t* name)
+{
+ etch_type_impl* impl = NULL;
+ etchparentinfo* inheritlist = NULL;
+ etch_type* newtype = new_id_name(name);
+ if (NULL == newtype) return NULL;
+ newtype->obj_type = ETCHTYPEB_TYPE;
+ newtype->class_id = CLASSID_ID_TYPE;
+
+ /* ensure parent type keys exist in (one-based) inheritance list */
+ inheritlist = get_vtab_inheritance_list((objmask*)newtype,
+ 2, 1, CLASSID_VTAB_FIELD);
+ inheritlist[1].obj_type = ETCHTYPEB_ID_NAME;
+ inheritlist[1].class_id = CLASSID_ID_NAME;
+
+ /* instantiate instance data */
+ impl = (etch_type_impl*) new_object(sizeof(etch_type_impl),
+ ETCHTYPEB_IDNAMEIMPL, CLASSID_TYPEIMPL);
+
+ impl->destroy = destroy_type_impl;
+ impl->async_mode = ETCH_ASYNCMODE_NONE; /* where is this default reset? */
+
+ impl->fieldmap = new_etchtype_fieldmap();
+ impl->vtormap = new_etchtype_vtormap();
+
+ newtype->impl = (etch_object*) impl;
+
+ newtype->destroy = destroy_type;
+ newtype->clone = clone_type;
+ return newtype;
+}
+
+
+/**
+ * new__static_type()
+ * create a type object whose destructor will have no effect.
+ */
+etch_type* new_static_type(const wchar_t* name)
+{
+ etch_type* newtype = new_type(name);
+ set_etchobj_static_all(newtype);
+ return newtype;
+}
+
+
+/**
+ * destroy_type()
+ * etch_type destructor
+ */
+int destroy_type(etch_type* type)
+{
+ if (type->refcount > 0 && --type->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(type)) /* e.g., not cloned */
+ {
+ if (type->impl)
+ { etch_type_impl* impl = (etch_type_impl*) type->impl;
+ impl->destroy(impl);
+ type->impl = NULL;
+ }
+ }
+
+ return destroy_id_name(type);
+}
+
+
+/**
+ * destroy_static_type()
+ * etch_type destructor.
+ * this should not be set as the virtual dtor for a type, since the type
+ * would then not be quasi-static as desired. it should be invoked explicitly
+ */
+int destroy_static_type(etch_type* type)
+{
+ clear_etchobj_static_all(type);
+ return destroy_type(type);
+}
+
+
+
+/**
+ * destroy_type_impl()
+ * etch_type_impl destructor
+ */
+int destroy_type_impl(etch_type_impl* impl)
+{
+ if (impl->refcount > 0 && --impl->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(impl))
+ { /* destruction of the maps causes all fields and non-cached validator
+ * objects, to be destroyed. see etchtype_fieldmap_clear_handler,
+ * and etchtype_vtormap_clear_handler, below. */
+ if (impl->vtormap)
+ impl->vtormap-> destroy(impl->vtormap);
+ if (impl->fieldmap)
+ impl->fieldmap->destroy(impl->fieldmap);
+ if (impl->impexphelper)
+ impl->impexphelper->destroy(impl->impexphelper);
+ }
+
+ return destroy_objectex((objmask*)impl);
+}
+
+
+/**
+ * clone_type()
+ * etch_type quasi copy constructor
+ * originally, type was simply a name and id. now a type has considerable extra
+ * content. we do not clone that content here, but rather copy its reference
+ * from the source and mark the clone as having non-disposable content such that
+ * the type destructor won't try to free it. so the object is not a true clone.
+ * note also that if the original were to be destroyed prior to the clone, the
+ * clone's content memory reference would be hosed; thus we must ensure that we
+ * only clone static types, i.e. types which are instantiated with the service,
+ * (or in the case of unit tests, emulated as such), and destroyed only at
+ * service teardown.
+ *
+ * note finally that etch_type and etch_idname still have the same footprint,
+ * with the type instantiating its extra content at the impl* of the id_name.
+ */
+etch_type* clone_type(const etch_type* type)
+{
+ etch_type* newtype = clone_id_name(type);
+ newtype->impl = type->impl;
+ set_etchobj_static_content(newtype);
+ return newtype;
+}
+
+
+/* - - - - - - - - - - - - - - - - - -
+ * get/set
+ * - - - - - - - - - - - - - - - - - -
+ */
+
+/* mutators are implemented only for instance data specific to type, i.e.
+ * resident in the etch_type_impl, following the c binding convention that we
+ * implement a mutator only when the datum can't safely be get/set directly.
+ */
+
+/**
+ * etchtype_set_type_stubhelper()
+ * set type's 'stub helper', returning existing helper if any.
+ * the stub helper is a function pointer, not an object.
+ */
+opaque_stubhelper etchtype_set_type_stubhelper(etch_type* type, opaque_stubhelper helper)
+{
+ /* sets a callback from message type to the particular API method implementation.
+ * note that in the the java binding this is indirect, that is, this callback
+ * calls a wrapper method which calls the implementation. however in our case,
+ * the methods have same signature, so we call the implementation directly.
+ * keep an eye on this though in case I have missed something.
+ */
+ opaque_stubhelper oldhelper = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { oldhelper = impl->stubhelper;
+ impl->stubhelper = helper;
+ }
+ return oldhelper;
+}
+
+
+/**
+ * etchtype_get_type_stubhelper()
+ * getter for stub helper - see comments at set_type_stubhelper()
+ */
+opaque_stubhelper etchtype_get_type_stubhelper(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->stubhelper: NULL;
+}
+
+
+/**
+ * etchtype_set_result_type()
+ * set result type, returning existing result type if any.
+ * @param type a non-disposable reference to a type.
+ * todo: if result type is set only at construction, lose this.
+ */
+etch_type* etchtype_set_result_type(etch_type* type, etch_type* rtype)
+{
+ etch_type* oldtype = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { oldtype = impl->result_type;
+ impl->result_type = rtype;
+ }
+ return oldtype;
+}
+
+
+/**
+ * etchtype_get_result_type()
+ * returns a non-disposable reference to result type
+ */
+etch_type* etchtype_get_result_type(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->result_type: NULL;
+}
+
+
+/**
+ * etchtype_set_super_type()
+ * todo: if set only at construction, lose this.
+ * @param a non-disposable type
+ * @return the previous type, not disposable.
+ */
+etch_type* etchtype_set_super_type(etch_type* type, etch_type* stype)
+{
+ etch_type* oldtype = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { oldtype = impl->super_type;
+ impl->super_type = stype;
+ }
+ return oldtype;
+}
+
+
+/**
+ * etchtype_get_super_type()
+ * returns a non-disposable reference to super type
+ */
+etch_type* etchtype_get_super_type(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->super_type: NULL;
+}
+
+
+/**
+ * etchtype_set_component_type()
+ * set associated component type and class for an array of this class.
+ * @param type a non-disposable type object. neither owned nor stored here.
+ * @return the existing objtype/classid representing component type.
+ */
+unsigned int etchtype_set_component_type(etch_type* type, unsigned int typeclass)
+{
+ unsigned int old_class = 0;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { old_class = impl->component_class;
+ impl->component_class = typeclass;
+ }
+ return old_class;
+}
+
+
+/**
+ * etchtype_get_component_type()
+ * returns component obj_type and class_id or zero indicating none set.
+ */
+unsigned int etchtype_get_component_type(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->component_class: 0;
+}
+
+
+/**
+ * etchtype_set_async_mode()
+ * set async_mode, which determines if requests are run on the queued or
+ * free thread pool.
+ */
+unsigned char etchtype_set_async_mode (etch_type* type, unsigned char mode)
+{
+ unsigned char old_mode = 0;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { old_mode = impl->async_mode;
+ impl->async_mode = mode;
+ }
+ return old_mode;
+}
+
+
+/**
+ * etchtype_get_async_mode()
+ * returns component async_mode
+ */
+unsigned char etchtype_get_async_mode (etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->async_mode: 0;
+}
+
+
+/**
+ * etchtype_set_timeout()
+ * set timeout to wait for response, in milliseconds.
+ */
+unsigned int etchtype_set_timeout(etch_type* type, unsigned int ms)
+{
+ unsigned int old_timeout = 0;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { old_timeout = impl->timeout;
+ impl->timeout = ms;
+ }
+ return old_timeout;
+}
+
+
+/**
+ * etchtype_get_timeout()
+ * get timeout to wait for response, in milliseconds.
+ */
+unsigned int etchtype_get_timeout(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->timeout: 0;
+}
+
+
+/**
+ * etchtype_set_run_validators()
+ * set boolean run validators flag, returning existing value.
+ */
+unsigned char etchtype_set_run_validators(etch_type* type, unsigned char val)
+{
+ unsigned char old_flag = 0;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { old_flag = impl->is_run_validators;
+ impl->is_run_validators = val;
+ }
+ return old_flag;
+}
+
+
+/**
+ * etchtype_get_response_field()
+ */
+etch_field* etchtype_get_response_field(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->response_field: NULL;
+}
+
+
+/**
+ * etchtype_set_response_field()
+ */
+etch_field* etchtype_set_response_field(etch_type* type, etch_field* field)
+{
+ etch_field* old_field = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { old_field = impl->response_field;
+ impl->response_field = field;
+ }
+ return old_field;
+}
+
+
+/**
+ * etchtype_get_run_validators()
+ * get boolean run validators flag.
+ */
+unsigned char etchtype_get_run_validators(etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return impl? impl->is_run_validators: 0;
+}
+
+
+/**
+ * etchtype_set_impexphelper()
+ * setter for import/export helper object
+ * @param helper the helper object to be assigned, or null.
+ * caller relinquishes ownership of this object if present.
+ * @return the *disposable* prior helper object if any.
+ * if present, caller now owns this object.
+ */
+etch_serializer* etchtype_set_impexphelper(etch_type* type, etch_serializer* helper)
+{
+ etch_serializer* oldhelper = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl)
+ { oldhelper = impl->impexphelper;
+ impl->impexphelper = helper;
+ }
+ return oldhelper;
+}
+
+
+/**
+ * etchtype_get_impexphelper()
+ * getter for import/export helper object
+ * @return a *non-disposable* reference to helper object.
+ * the type retains ownership of this object.
+ */
+etch_serializer* etchtype_get_impexphelper(etch_type* type)
+{
+ etch_type_impl* impl = type? (etch_type_impl*) type->impl: NULL;
+ return impl? impl->impexphelper: NULL;
+}
+
+
+/**
+ * etchtype_is_assignable_from()
+ * indicate if this type is assignable from other, i.e. other a subclass of this
+ */
+int etchtype_is_assignable_from(etch_type* type, etch_type* othertype)
+{
+ etch_type* other_supertype;
+ if (NULL == othertype) return FALSE;
+ if (is_equal_types(type, othertype)) return TRUE;
+ other_supertype = othertype->impl?
+ ((etch_type_impl*)othertype->impl)->super_type: NULL;
+ return etchtype_is_assignable_from(type, other_supertype);
+}
+
+
+/* - - - - - - - - - - - - - - - - -
+ * fieldmap accessors
+ * - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * get_key_by_name()
+ * look up an etch_id_name key object by a name string. recall that etch_type
+ * and etch_field each are typedefs of etch_id_name. id_name derivations are
+ * keyed by hash of name, so lookup is direct;
+ */
+etch_id_name* etchtype_get_key_by_name(etch_hashtable* map, const wchar_t* name)
+{
+ etch_hashitem hashbucket, *thisitem = &hashbucket;
+ const unsigned hashkey = etch_get_wchar_hashkey(name);
+ const int result = map->vtab->findh(map->realtable, hashkey, map, &thisitem);
+ return result == 0? (etch_id_name*) thisitem->key: NULL;
+}
+
+
+/**
+ * get_idname_by_id()
+ * given a hashtable and an id_name "id", return the map's id_name key having that id.
+ * note that a non-disposable *reference* is returned, not a copy.
+ */
+etch_id_name* etchtype_get_key_by_id (etch_hashtable* map, const unsigned id)
+{
+ etch_iterator iterator;
+ set_iterator(&iterator, map, &map->iterable);
+
+ while(iterator.has_next(&iterator))
+ {
+ etch_id_name* this_idname = (etch_id_name*) iterator.current_key;
+ if (this_idname->id == id) return this_idname;
+ iterator.next(&iterator);
+ }
+
+ return NULL;
+}
+
+
+/**
+ * etchtype_add_field()
+ * adds a field to set of fields
+ * @param field caller must supply a disposable field object.
+ * @return the argument. If there is a name collision, the existing field
+ * is returned in place of the supplied field, AND the supplied field is
+ * DESTROYED. this simplifies logic up the line, and is consistent with caller
+ * expecting to relinquish responsibility for the field passed.
+ */
+etch_field* etchtype_add_field (etch_type* type, etch_field* field)
+{
+ etch_field *effective_field = field;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ etch_hashtable* map = impl->fieldmap;
+
+ int result = impl->fieldmap->vtab->inserth
+ (map->realtable, field, NULL, map, 0);
+
+ if (-1 == result)
+ effective_field = etchtype_get_field_by_name(type, field->name);
+
+ if (effective_field != field)
+ field->destroy(field);
+
+ #ifdef ETCHTYPE_DEBUG
+ if (effective_field)
+ wprintf(L"add field %08x '%s'\n",
+ (size_t) (void*) effective_field, effective_field->name);
+ else wprintf(L"error adding field '%s'\n", field->name);
+ #endif
+
+ return effective_field;
+}
+
+
+/**
+ * etchtype_get_field_by_id()
+ * @return a non-disposable reference to the requested field, or null
+ */
+etch_field* etchtype_get_field_by_id (etch_type* type, const unsigned id)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return etchtype_get_key_by_id(impl->fieldmap, id);
+}
+
+
+/**
+ * etchtype_get_field_by_name()
+ * works as in the java binding, in that if the type does not include
+ * a field with that name, a new field is created and added to the type.
+ * @return a non-disposable reference to the requested field, or null
+ */
+etch_field* etchtype_get_field_by_name (etch_type* type, const wchar_t* name)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ etch_field* field = etchtype_get_key_by_name(impl->fieldmap, name);
+ if (NULL == field)
+ field = etchtype_add_field (type, new_field(name));
+ return field;
+}
+
+
+/**
+ * etchtype_get_fields()
+ * returns a disposable arraylist of references. the list is marked
+ * such that list->destroy() will not attempt to free content.
+ * caller must cast result to etch_arraylist*
+ */
+void* etchtype_get_fields (etch_type* type)
+{
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ return get_map_keys(impl->fieldmap);
+}
+
+
+/*
+ * etchtype_fields_count()
+ * return count of fields resident in the type.
+ */
+int etchtype_fields_count(etch_type* type)
+{
+ int count = 0;
+ etch_hashtable* map = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl) map = impl->fieldmap;
+ if (map) count = map->vtab->count(map->realtable, 0, 0);
+ return count;
+}
+
+
+/*
+ * etchtype_set_fields_iterator()
+ * initialize iterator over fields.
+ */
+int etchtype_set_fields_iterator(etch_type* type, etch_iterator* iterator)
+{
+ etch_hashtable* map = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl) map = impl->fieldmap;
+ return map? set_iterator(iterator, map, &map->iterable): -1;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - -
+ * validator insert/lookup
+ * - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * etchtype_get_validator_by_id()
+ * caller will want to cast result to etch_validator*.
+ * note that the etch_type header can't include etch_validator header,
+ * thus the anonymous pointers to etch_validator in these methods.
+ */
+objmask* etchtype_get_validator_by_id (etch_type* type, const unsigned id)
+{
+ int result = 0;
+ etch_hashtable* map;
+ etch_iterator iterator;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (!impl || !id) return NULL;
+ map = impl->vtormap;
+
+ set_iterator(&iterator, map, &map->iterable);
+
+ while(iterator.has_next(&iterator))
+ {
+ etch_field* this_field = (etch_field*) iterator.current_key;
+ if (this_field->id == id)
+ return iterator.current_value;
+ iterator.next(&iterator);
+ }
+
+ return NULL;
+}
+
+
+/**
+ * etchtype_get_validator_by_name()
+ * @param name the name of the etch_field keying the validator.
+ * caller will want to cast result to etch_validator*
+ */
+objmask* etchtype_get_validator_by_name (etch_type* type, const wchar_t* name)
+{
+ etch_type_impl* impl = type? (etch_type_impl*) type->impl: NULL;
+
+ if (impl && name)
+ {
+ etch_hashitem hashbucket, *thisitem = &hashbucket;
+ etch_hashtable* map = impl->vtormap;
+ const unsigned key = etch_get_wchar_hashkey(name);
+ if (0 == map->vtab->findh(map->realtable, key, map, &thisitem))
+ return thisitem->value;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * etchtype_put_validator()
+ * adds a validator to validator chain for specified key
+ * @param field relinquished regardless of result.
+ * @param new_vtor relinquished regardless of result.
+ */
+int etchtype_put_validator (etch_type* type, etch_field* field, objmask* new_vtor)
+{
+ int result = -1;
+ etch_hashtable *fmap, *vmap;
+ etch_hashitem hashbucket, *mapentry = &hashbucket;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ ETCH_ASSERT(impl);
+
+ do /* validate parameters */
+ { if (!is_etch_validator(new_vtor))
+ { ETCHOBJ_DESTROY(field);
+ break;
+ }
+
+ if (NULL == field)
+ { ETCHOBJ_DESTROY(new_vtor);
+ break;
+ }
+
+ result = 0;
+
+ } while(0);
+
+ if (0 != result) return result;
+
+ if (!impl || !is_etch_validator(new_vtor) || !field) return -1;
+ memset(mapentry, 0, sizeof(etch_hashitem));
+ fmap = impl->fieldmap;
+ vmap = impl->vtormap;
+
+ /* add field to fieldmap. if an eponymous field was present, it is returned
+ * in place of caller's field, and caller's field has been destroyed. */
+ field = etchtype_add_field (type, field);
+
+ /* if a validator exists under the specified key, we'll chain the new
+ * validator to the existing validator with a new combo validator object,
+ * and replace the current vtor map entry with the new combo validator.
+ */
+ result = vmap->vtab->removeh /* if already in vtormap, remove it */
+ (vmap->realtable, field->hashkey, vmap, &mapentry);
+
+ if (result == -1) /* if it was not already in vtormap, insert it */
+ result = vmap->vtab->inserth (vmap->realtable,
+ field->clone(field), new_vtor, vmap, 0);
+ else /* ... otherwise insert a new chain head */
+ { etch_field* existing_key = (etch_field*) mapentry->key;
+ etch_validator* existing_vtor = (etch_validator*) mapentry->value;
+
+ etch_validator* vcombo /* chain new vtor to existing vtor ... */
+ = new_combo_validator(existing_vtor, (etch_validator*) new_vtor);
+
+ result = vmap->vtab->inserth /* ... and insert the new chained vtor */
+ (vmap->realtable, existing_key, vcombo, vmap, 0);
+ }
+
+ return result;
+}
+
+
+/*
+ * etchtype_clear_validator()
+ * remove the validator chain for specified key.
+ */
+int etchtype_clear_validator(etch_type* type, etch_field* key)
+{
+ int result = -1;
+ etch_hashtable* map = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl) map = impl->vtormap;
+
+ if (map)
+ { etch_validator* removed_vtor = NULL;
+ etch_hashitem hashbucket, *mapentry = &hashbucket;
+ memset(mapentry, 0, sizeof(etch_hashitem));
+
+ result = map->vtab->removeh /* remove from map, returning content */
+ (map->realtable, key->hashkey, map, &mapentry);
+
+ if (result == 0) /* returned content is head of validator chain */
+ {
+ removed_vtor = (etch_validator*) mapentry->value;
+
+ destroy_type((etch_type*) mapentry->key);
+ }
+
+ if (removed_vtor) /* destructors are called up the chain */
+ result = removed_vtor->destroy(removed_vtor);
+ }
+
+ return result;
+}
+
+
+/*
+ * etchtype_clear_validators()
+ * clear all type validators. non-cached validators are destroyed.
+ * returns count of items cleared, or -1 if error.
+ */
+int etchtype_clear_validators(etch_type* type)
+{
+ int result = -1;
+ etch_hashtable* map = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl) map = impl->vtormap;
+ if (map) /* we ask hashtable clear() to call content destructors */
+ result = map->vtab->clear(map->realtable, FALSE, TRUE, map, 0);
+ return result;
+}
+
+
+/*
+ * etchtype_validators_count()
+ * return count of validators in chain.
+ */
+int etchtype_validators_count(etch_type* type)
+{
+ int count = 0;
+ etch_hashtable* map = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl) map = impl->vtormap;
+ if (map) count = map->vtab->count(map->realtable, 0, 0);
+ return count;
+}
+
+
+/*
+ * etchtype_set_validators_iterator()
+ * initialize iterator over validators.
+ */
+int etchtype_set_validators_iterator(etch_type* type, etch_iterator* iterator)
+{
+ etch_hashtable* map = NULL;
+ etch_type_impl* impl = (etch_type_impl*) type->impl;
+ if (impl) map = impl->vtormap;
+ return map? set_iterator(iterator, map, &map->iterable): -1;
+}
+
+
+/* - - - - - - - - - - - - - - - - - -
+ * utility methods
+ * - - - - - - - - - - - - - - - - - -
+ */
+
+/*
+ * etchtype_fieldmap_clear_handler()
+ * callback set to handle freeing of key memory during a clear() of the fields
+ * map. note that this map is used as a quasi set, so the value is always null.
+ * the etch_fields are owned by the map and destroyed as the map is destroyed.
+ * handlers return FALSE to indicate memory free NOT handled.
+ */
+int etchtype_fieldmap_clear_handler (void* key, void* value)
+{
+ ((objmask*)key)->destroy(key);
+ return TRUE;
+}
+
+
+/**
+ * new_etchtype_fieldmap()
+ * construct and return a hashtable configured as expected for the fieldmap
+ */
+etch_hashtable* new_etchtype_fieldmap()
+{
+ etch_hashtable* map = new_synchronized_hashtable(ETCHTYPE_DEFSIZE_FIELDMAP);
+ if (NULL == map) return NULL;
+ map->content_type = ETCHHASHTABLE_CONTENT_OBJECT;
+ map->is_tracked_memory = TRUE;
+ map->is_readonly_keys = FALSE; /* keys are disposable field objects */
+ map->is_readonly_values = FALSE; /* value is always null */
+ map->freehook = etchtype_fieldmap_clear_handler;
+ return map;
+}
+
+
+/*
+ * etchtype_vtormap_clear_handler()
+ * callback set to handle freeing of field and validator memory
+ * during a clear() of the validators map.
+ */
+int etchtype_vtormap_clear_handler (void* key, void* value)
+{
+ /* note that value->destroy() is invoking the validator destructor,
+ * and that this will have no effect on a validator marked as cached */
+ if (value) ((objmask*)value)->destroy(value);
+ if (key) ((objmask*)key)->destroy(key);
+ return TRUE;
+}
+
+
+/**
+ * new_etchtype_vtormap()
+ * construct and return a hashtable configured as expected for validators.
+ * this is a map of non-disposable etch_field keys to etch_validator*
+ * object references. the validators are considered as disposable, in that
+ * clearing the map will result in validator destructor calls; however
+ * note that destroy() has no effect on a cached validator - these are
+ * not destroyed until such time as the validator cache is cleared.
+ */
+etch_hashtable* new_etchtype_vtormap()
+{
+ etch_hashtable* map = new_synchronized_hashtable(ETCHTYPE_DEFSIZE_VTORMAP);
+ if (NULL == map) return NULL;
+ map->content_type = ETCHHASHTABLE_CONTENT_OBJECT;
+ map->is_tracked_memory = TRUE;
+ map->is_readonly_keys = TRUE; /* keys are nondisposable field objects */
+ map->is_readonly_values = FALSE; /* values are validator function pointers */
+ map->freehook = etchtype_vtormap_clear_handler;
+ return map;
+}
+
Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_validator.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_validator.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_validator.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_validator.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,1748 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * etch_validator.c
+ * validators
+ */
+
+#include "etch_validator.h"
+#include "etch_tagdata.h"
+#include "etch_global.h"
+#include "etch_arrayval.h"
+#include "etch_structval.h"
+#include "etch_encoding.h"
+#include "etch_type.h"
+#pragma warning (disable:4996)
+
+/* cached validators have private constructors,
+ * get() is the public method of construction and caching
+ */
+etch_validator* new_validator_boolean(const int dimensions);
+etch_validator* new_validator_byte (const int dimensions);
+etch_validator* new_validator_int8 (const int dimensions);
+etch_validator* new_validator_int16 (const int dimensions);
+etch_validator* new_validator_int32 (const int dimensions);
+etch_validator* new_validator_int64 (const int dimensions);
+etch_validator* new_validator_float (const int dimensions);
+etch_validator* new_validator_double (const int dimensions);
+etch_validator* new_validator_string (const int dimensions);
+etch_validator* new_validator_object (const int dimensions);
+etch_validator* new_validator_exception();
+etch_validator* new_validator_eod();
+
+int etch_typevtor_validate(etch_validator*, etch_object*);
+int etch_typevtor_check_value(etch_validator*, etch_object*, byte*);
+etch_validator* etch_typevtor_element_validator(etch_validator*);
+
+etch_object* etch_typevtor_validate_value(etch_validator*, etch_object*);
+etch_validator* etchvtor_cache_validator(etch_validator*, etch_validator** cache);
+etch_validator* new_type_validator(const unsigned short vtor_classid,
+ const unsigned short scalar_obj_type, const unsigned short scalar_classid,
+ const unsigned short array_classid, const int ndims, char* description);
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * contructors, destructors
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * destroy_validator()
+ * validator object destructor
+ */
+int destroy_validator(etch_validator* vtor)
+{
+ /* don't honor destroy() request if object is cached */
+ if (vtor->is_cached) return -1;
+
+ if (vtor->refcount > 0 && --vtor->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(vtor))
+ etch_free(vtor->description);
+
+ return destroy_objectex((objmask*)vtor);
+}
+
+
+/**
+ * new_validator_from()
+ * constructor for etch_validator
+ */
+etch_validator* new_validator()
+{
+ return new_validator_from(NULL, NULL, NULL, NULL);
+}
+
+
+/**
+ * new_validator_from()
+ * constructor 2 for etch_validator
+ */
+etch_validator* new_validator_from(etchvtor_validate fv, etchvtor_checkvalue fcv,
+ etchvtor_element_validator fev, etchvtor_validate_value fvv)
+{
+ etch_validator* newvtor = (etch_validator*) new_object(sizeof(etch_validator),
+ ETCHTYPEB_VALIDATOR, CLASSID_VALIDATOR);
+
+ newvtor->destroy = destroy_validator;
+ newvtor->validate = fv;
+ newvtor->check_value = fcv;
+ newvtor->element_validator = fev;
+ newvtor->validate_value = fvv;
+
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * validator cache
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * etchvtor_cache_validator()
+ * convenience method to cache specified validator, marking it cached.
+ */
+etch_validator* etchvtor_cache_validator(etch_validator* vtor, etch_validator** cache)
+{
+ cache[vtor->numdimensions] = vtor; /* assumed pre-validated by caller */
+ vtor->is_cached = TRUE;
+ return vtor;
+}
+
+
+/**
+ * etchvtor_clear_cache()
+ * clear the validator cache, destroying any validators found
+ */
+void etchvtor_clear_cache()
+{
+ const int cachebytes = ETCHVTOR_BYTES_PER_CACHE * ETCHVTOR_CACHED_TYPE_COUNT;
+ const int cacheslots = cachebytes / sizeof(void*);
+ int i=0;
+
+ for(; i < cacheslots; i++)
+ {
+ etch_validator* p = etchvtor_cache[i];
+ if (p == NULL || p->obj_type != ETCHTYPEB_VALIDATOR) continue;
+ p->is_cached = FALSE;
+ p->destroy(p);
+ }
+
+ memset(etchvtor_cache, 0, cachebytes);
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * combo validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+
+/**
+ * etch_combovtor_validate()
+ * combo validator default validate() virtual
+ */
+int etch_combovtor_validate(etch_validator* vtor, etch_object* value)
+{
+ int resulta = 0, resultb = 0;
+ etch_validator *vtor_a = vtor->vtor_a, *vtor_b = vtor->vtor_b;
+
+ resulta = vtor_a? vtor_a->validate(vtor_a, value): -1;
+ if (0 == resulta) return 0;
+
+ resultb = vtor_b? vtor_b->validate(vtor_b, value): -1;
+ return resultb;
+}
+
+
+/**
+ * etch_combovtor_validate_value()
+ * combo validator default validate_value() virtual
+ * note carefully: the returned value may or may not be the same object
+ * as the passed value. see comments later in this module.
+ */
+etch_object* etch_combovtor_validate_value(etch_validator* vtor, etch_object* value)
+{
+ int resulta = 0, resultb = 0;
+ etch_validator *vtor_a = vtor->vtor_a, *vtor_b = vtor->vtor_b;
+ etch_object *validatedobj = NULL;
+
+ validatedobj = vtor_a? vtor_a->validate_value(vtor_a, value): NULL;
+
+ if (NULL == validatedobj)
+ validatedobj = vtor_b? vtor_b->validate_value(vtor_b, value): NULL;
+
+ return validatedobj;
+}
+
+
+/**
+ * etch_combovtor_check_value()
+ * combo validator default check_value() virtual
+ */
+int etch_combovtor_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ byte typecode = 0;
+ int resulta = 0, resultb = 0;
+ etch_validator *vtor_a = vtor->vtor_a, *vtor_b = vtor->vtor_b;
+
+ resulta = vtor_a? vtor_a->check_value(vtor_a, value, &typecode): -1;
+ if (-1 == resulta)
+ { resultb = vtor_b? vtor_b->check_value(vtor_b, value, &typecode): -1;
+ if (-1 == resultb) return -1;
+ }
+
+ *typecode_out = typecode;
+ return 0;
+}
+
+
+/**
+ * etch_combovtor_element_validator()
+ * combo validator default element_validator() virtual
+ */
+etch_validator* etch_combovtor_element_validator(etch_validator* vtor)
+{
+ int resulta = 0, resultb = 0;
+ etch_validator *vtor_a = vtor->vtor_a, *vtor_b = vtor->vtor_b;
+
+ etch_validator *eltvtor_a = vtor_a? vtor_a->element_validator(vtor_a): NULL;
+ etch_validator *eltvtor_b = vtor_b? vtor_b->element_validator(vtor_b): NULL;
+
+ if (eltvtor_a == NULL && eltvtor_b == NULL) return NULL;
+ if (eltvtor_a == NULL) return eltvtor_b;
+ if (eltvtor_b == NULL) return eltvtor_a;
+ return new_combo_validator(eltvtor_a, eltvtor_b);
+}
+
+
+/**
+ * destroy_combo_validator()
+ * combo validator destructor
+ * destroys all validators in the chain
+ */
+int destroy_combo_validator(etch_validator* vtor)
+{
+ if (vtor->is_cached) return -1;
+
+ if (vtor->refcount > 0 && --vtor->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(vtor))
+ {
+ if (vtor->vtor_a)
+ vtor->vtor_a->destroy(vtor->vtor_a);
+
+ if (vtor->vtor_b)
+ vtor->vtor_b->destroy(vtor->vtor_b);
+
+ etch_free(vtor->description);
+ }
+
+ return destroy_objectex((objmask*)vtor);
+}
+
+
+/**
+ * new_combo_validator()
+ * constructor for combo validator.
+ * caveat: the destructor frees memory for all validators in the chain.
+ * if the same validator reference were to appear more than once in a chain,
+ * it must be either a reference from the cache, or otherwise marked such that
+ * the destructor will not attempt to free it (validator marked as static,
+ * or combo parent marked as static content). the safest way to chain non-
+ * cached validators is to ensure that each chained validator reference is
+ * unique, i.e. newly instantiated.
+ */
+etch_validator* new_combo_validator(etch_validator* vtor_a, etch_validator* vtor_b)
+{
+ etch_validator* newvtor = new_validator_from
+ (etch_combovtor_validate,
+ etch_combovtor_check_value,
+ etch_combovtor_element_validator,
+ etch_combovtor_validate_value);
+
+ newvtor->class_id = CLASSID_COMBO_VALIDATOR;
+ newvtor->destroy = destroy_combo_validator;
+ newvtor->vtor_a = vtor_a;
+ newvtor->vtor_b = vtor_b;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * type validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * new_type_validator()
+ * private constructor for a type validator
+ */
+etch_validator* new_type_validator(const unsigned short vtor_classid,
+ const unsigned short scalar_obj_type, const unsigned short scalar_classid,
+ const unsigned short array_classid, const int ndims, char* description)
+{
+ etch_validator* newvtor = new_validator();
+ newvtor->class_id = vtor_classid;
+ newvtor->expected_class_id = ndims? array_classid: scalar_classid;
+ newvtor->numdimensions = ndims;
+ newvtor->description = new_char(description);
+ newvtor->validate_value = etch_typevtor_validate_value;
+ newvtor->validate = etch_typevtor_validate;
+ newvtor->check_value = etch_typevtor_check_value;
+ newvtor->element_validator = etch_typevtor_element_validator;
+ return newvtor;
+}
+
+
+/**
+ * new_type_validator_1()
+ * constructor for a type validator for types using inheritance scheme 1
+ * @param vtable_class_id the class of the expected class' vtable, zero if the
+ * class inherits only from object. the class inheritance list if any is fetched
+ * from the cached vtable, and is not disposable.
+ */
+etch_validator* new_type_validator_1(const unsigned short vtor_classid,
+ const unsigned short scalar_obj_type, const unsigned short scalar_classid,
+ const unsigned short vtable_class_id, const unsigned short array_classid,
+ const int ndims, char* description)
+{
+ etch_validator* newvtor = new_type_validator(vtor_classid, scalar_obj_type,
+ scalar_classid, array_classid, ndims, description);
+
+ if (vtable_class_id)
+ { /* cache a reference to the expected class' inheritance list if any */
+ vtabmask* vtab = cache_find(get_vtable_cachehkey(vtable_class_id), 0);
+ if (vtab)
+ { newvtor->inherits_from = vtab->inherits_from;
+ newvtor->is_owned_inherits_from = FALSE;
+ }
+ }
+
+ return newvtor;
+}
+
+
+/**
+ * new_type_validator_2()
+ * constructor for a type validator
+ * @param inherit_list a complete and disposable inheritance list for the class.
+ * for classes inheriting via method 2 that have more than two objects in the
+ * inheritance chain, this list must be artificially created, since no object
+ * in the chain will have a complete list.
+ */
+etch_validator* new_type_validator_2(const unsigned short vtor_classid,
+ const unsigned short scalar_obj_type, const unsigned short scalar_classid,
+ const unsigned short array_classid, etchparentinfo* inherit_list,
+ const int ndims, char* description)
+{
+ etch_validator* newvtor = new_type_validator(vtor_classid, scalar_obj_type,
+ scalar_classid, array_classid, ndims, description);
+
+ newvtor->inherits_from = inherit_list;
+ newvtor->is_owned_inherits_from = TRUE;
+ return newvtor;
+}
+
+
+/**
+ * etch_typevtor_check_dimensions()
+ * convenience function to validate dimension count
+ */
+int etchvtor_check_dimensions(const int ndims)
+{
+ return ndims < 0 || ndims > ETCHVTOR_MAX_NDIMS? -1: 0;
+}
+
+
+/**
+ * etchvtor_set_classparams()
+ * populate arguments to etchobj_is_assignable_from(), for use by validate()
+ */
+void etchvtor_set_classparams(etch_objclass* targetparams,
+ etch_objclass* sourceparams, etch_validator* targetvtor, objmask* sourceobj)
+{
+ memset(targetparams, 0, sizeof(etch_objclass));
+ targetparams->obj_type = targetvtor->expected_obj_type;
+ targetparams->class_id = targetvtor->expected_class_id;
+ targetparams->numdims = targetvtor->numdimensions;
+ targetparams->inherits_from = targetvtor->inherits_from;
+
+ set_etch_assignable_arg_from(sourceparams, sourceobj);
+}
+
+
+/**
+ * etch_typevtor_validate()
+ * type validator default validate() virtual
+ */
+int etch_typevtor_validate(etch_validator* vtor, etch_object* value)
+{
+ int result = 0, source_numdims = 0;
+ if (!value) return -1;
+
+ /* java uses different classes for arrays of the same type but different
+ * dimensions. we do not, so we also validate dimensions of array objects
+ * to augment class comparison.
+ */
+ if (is_etch_object_type(value->obj_type, value->class_id)) return 0;
+
+ switch(value->obj_type)
+ { case ETCHTYPEB_NATIVEARRAY:
+ source_numdims = ((etch_nativearray*)value)->numdims;
+ break;
+ case ETCHTYPEB_ARRAYVAL:
+ source_numdims = ((etch_arrayvalue*)value)->dim;
+ break;
+ case ETCHTYPEB_ARRAYLIST:
+ source_numdims = 1;
+ break;
+ }
+
+ #if(0)
+ /* this validation was moved to the object validator's validate() */
+ if (is_etch_object_type(value->obj_type, value->class_id) && vtor->numdims == 0)
+ result = 0;
+ else
+ #endif
+ if (source_numdims != vtor->numdimensions)
+ result = -1;
+ else
+ if (value->class_id != vtor->expected_class_id)
+ {
+ /* objects not same class: verify source class assignable to target */
+ etch_objclass target, source;
+ etchvtor_set_classparams(&target, &source, vtor, (objmask*) value);
+
+ if (etchobj_is_assignable_from(&target, &source));
+ else result = -1;
+ }
+
+ return result;
+}
+
+
+/**
+ * etch_typevtor_check_value()
+ * default implementation
+ */
+int etch_typevtor_check_value(etch_validator* v, etch_object* x, byte* tc)
+{
+ return -1;
+}
+
+
+/**
+ * etch_typevtor_element_validator()
+ * default implementation
+ */
+etch_validator* etch_typevtor_element_validator(etch_validator* v)
+{
+ return NULL;
+}
+
+
+/**
+ * etch_typevtor_validate_value()
+ * type validator default validate_value() virtual.
+ * note carefully: the returned value may or may not be the same object as the
+ * passed value. the reason for this clunkiness is the port from java, in which
+ * the original could simply be abandoned. the caller must therefore test if the
+ * objects are the same, and if not, destroy the original. for this reason also,
+ * this method should not be called with the same symbol specified for both the
+ * passed and return objects, for this would leak memory.
+ * note further: the further reason for this is, for example, that the caller
+ * may get back an etch_byte*, but the object being validated is an etch_int32*
+ * whose value is downsized into a newly instantiated etch_byte. we have padded
+ * out all the primitives to have 8 bytes after the header, so we could, if need
+ * be, morph the object passed to validate_value to be the validated object type.
+ * for example, if we passed an etch_int32 with value 1 to the byte validator,
+ * currently byte's validate_value would instantiate and return a new etch_byte,
+ * but we could easily change the etch_int32 to an etch_byte, if this would help.
+ */
+etch_object* etch_typevtor_validate_value(etch_validator* vtor, etch_object* value)
+{
+ return (0 == vtor->validate(vtor, value))? value: NULL;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * boolean validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_boolean /* boolean validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_BOOLEAN * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_boolean_get()
+ * get a boolean validator for specified dimensions
+ */
+etch_validator* etchvtor_boolean_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_boolean(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_boolean[ndims]))
+ vtor = etchvtor_cache_validator
+ (new_validator_boolean(ndims), etchvtor_cache_boolean);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_boolean_check_value()
+ * check_value override for boolean validator
+ * returns external type of specified value
+ */
+int etchvtor_boolean_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, value)) return -1;
+
+ if (vtor->numdimensions > 0)
+ *typecode_out = ETCH_XTRNL_TYPECODE_ARRAY;
+ else *typecode_out =((etch_boolean*)value)->value?
+ ETCH_XTRNL_TYPECODE_BOOLEAN_TRUE: ETCH_XTRNL_TYPECODE_BOOLEAN_FALSE;
+
+ return 0;
+}
+
+
+/**
+ * etchvtor_boolean_element_validator()
+ * element_validator override for boolean validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_boolean_element_validator(etch_validator* vtor)
+{
+ return etchvtor_boolean_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_boolean()
+ * constructor for boolean validator
+ */
+etch_validator* new_validator_boolean(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "bool[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_BOOL, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_BOOL, 0, CLASSID_ARRAY_BOOL, numdimensions, name);
+
+ newvtor->check_value = etchvtor_boolean_check_value;
+ newvtor->element_validator = etchvtor_boolean_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * byte validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_byte /* byte validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_BYTE * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_byte_get()
+ * get a byte validator for specified dimensions
+ */
+etch_validator* etchvtor_byte_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_byte(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_byte[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_byte(ndims), etchvtor_cache_byte);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_byte_validate()
+ * validate() override verifying value is in range of byte
+ */
+int etchvtor_byte_validate(etch_validator* vtor, etch_object* value)
+{
+ if (vtor->numdimensions > 0)
+ return etch_typevtor_validate(vtor, value);
+
+ if (NULL == value) return -1;
+
+ switch(value->class_id)
+ { case CLASSID_PRIMITIVE_BYTE:
+ return 0;
+ case CLASSID_PRIMITIVE_INT32:
+ return is_inrange_byte(((etch_int32*)value)->value)? 0: -1;
+ case CLASSID_PRIMITIVE_INT64:
+ return is_inrange_byte(((etch_int64*)value)->value)? 0: -1;
+ case CLASSID_PRIMITIVE_INT16:
+ return is_inrange_byte(((etch_int16*)value)->value)? 0: -1;
+ case CLASSID_PRIMITIVE_BOOL:
+ return is_inrange_bool(((etch_boolean*)value)->value)? 0: -1;
+ case CLASSID_PRIMITIVE_INT8:
+ return is_inrange_byte(((etch_int8*)value)->value)? 0: -1;
+ }
+
+ return -1;
+}
+
+
+/**
+ * etchvtor_byte_check_value()
+ * check_value override for byte validator
+ * returns external type of specified value
+ */
+int etchvtor_byte_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, value)) return -1;
+
+ switch(vtor->numdimensions)
+ { case 0: *typecode_out = ETCH_XTRNL_TYPECODE_BYTE; break;
+ case 1: *typecode_out = ETCH_XTRNL_TYPECODE_BYTES; break;
+ default: *typecode_out = ETCH_XTRNL_TYPECODE_ARRAY;
+ }
+
+ return 0;
+}
+
+
+/**
+ * etchvtor_byte_validate_value()
+ * validate_value override for byte validator
+ */
+etch_object* etchvtor_byte_validate_value(etch_validator* vtor, etch_object* value)
+{
+ byte byteval = 0;
+
+ etch_object* valobj = etch_typevtor_validate_value(vtor, value);
+ if (NULL == valobj) return NULL;
+
+ /* here, the returned object is the passed object, caller does no cleanup */
+ if (vtor->numdimensions > 0 || is_etch_byte(value)) return value;
+
+ if (-1 == etchtagdata_byte_value (value, &byteval)) return NULL;
+
+ /* here, the returned object is not the same as the passed object,
+ * so caller must replace the reference, and destroy the passed object */
+ return (etch_object*) new_byte(byteval);
+}
+
+
+/**
+ * etchvtor_byte_element_validator()
+ * element_validator override for byte validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_byte_element_validator(etch_validator* vtor)
+{
+ return etchvtor_byte_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_byte()
+ * constructor for byte validator
+ */
+etch_validator* new_validator_byte(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "byte[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_BYTE, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_BYTE, 0, CLASSID_ARRAY_BYTE, numdimensions, name);
+
+ newvtor->validate = etchvtor_byte_validate;
+ newvtor->check_value = etchvtor_byte_check_value;
+ newvtor->validate_value = etchvtor_byte_validate_value;
+ newvtor->element_validator = etchvtor_byte_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * int8 validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_int8 /* int8 validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_INT8 * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_int8_get()
+ * get a int8 validator for specified dimensions
+ */
+etch_validator* etchvtor_int8_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_int8(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_int8[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_int8(ndims), etchvtor_cache_int8);
+ return vtor;
+}
+
+
+/**
+ * new_validator_int8()
+ * constructor for int8 validator
+ */
+etch_validator* new_validator_int8(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "int8[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_INT8, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_INT8, 0, CLASSID_ARRAY_INT8, numdimensions, name);
+
+ newvtor->validate = etchvtor_byte_validate;
+ newvtor->check_value = etchvtor_byte_check_value;
+ newvtor->validate_value = etchvtor_byte_validate_value;
+ newvtor->element_validator = etchvtor_byte_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * int16 validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+etch_validator** etchvtor_cache_int16 /* int16 validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_INT16 * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_int16_get()
+ * get a int16 validator for specified dimensions
+ */
+etch_validator* etchvtor_int16_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_int16(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_int16[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_int16(ndims), etchvtor_cache_int16);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_int16_validate()
+ * validate() override verifying value is in range of short
+ */
+int etchvtor_int16_validate(etch_validator* vtor, etch_object* value)
+{
+ int result = -1;
+
+ if (vtor->numdimensions > 0)
+ result = etch_typevtor_validate(vtor, value);
+ else
+ if (NULL == value)
+ result = -1;
+ else switch(value->class_id)
+ { case CLASSID_PRIMITIVE_BYTE:
+ case CLASSID_PRIMITIVE_INT8:
+ case CLASSID_PRIMITIVE_INT16:
+ result = 0;
+ break;
+ case CLASSID_PRIMITIVE_INT32:
+ if (is_inrange_int16(((etch_int32*)value)->value))
+ result = 0;
+ break;
+ case CLASSID_PRIMITIVE_INT64:
+ if (is_inrange_int16(((etch_int64*)value)->value))
+ result = 0;
+ }
+
+ return result;
+}
+
+
+/**
+ * etchvtor_int16_check_value()
+ * check_value override for int16 validator
+ * returns external type of specified value
+ */
+int etchvtor_int16_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ short shortval = 0;
+ int result = vtor->validate(vtor, value);
+
+ if (-1 == result);
+ else
+ if (vtor->numdimensions)
+ *typecode_out = ETCH_XTRNL_TYPECODE_ARRAY;
+ else
+ if (-1 == (result = etchtagdata_int16_value(value, &shortval)));
+ else
+ if (is_inrange_byte(shortval))
+ *typecode_out = ETCH_XTRNL_TYPECODE_BYTE;
+ else *typecode_out = ETCH_XTRNL_TYPECODE_SHORT;
+
+ return result;
+}
+
+
+/**
+ * etchvtor_int16_validate_value()
+ * validate_value override for short int validator
+ */
+etch_object* etchvtor_int16_validate_value(etch_validator* vtor, etch_object* value)
+{
+ short shortval = 0;
+
+ etch_object* valobj = etch_typevtor_validate_value(vtor, value);
+ if (NULL == valobj) return NULL;
+
+ /* here, the returned object is the passed object, caller does no cleanup */
+ if (vtor->numdimensions > 0 || is_etch_int16(value)) return value;
+
+ if (-1 == etchtagdata_int16_value (value, &shortval)) return NULL;
+
+ /* here, the returned object is not the same as the passed object,
+ * so caller must replace the reference, and destroy the passed object */
+ return (etch_object*) new_int16(shortval);
+}
+
+
+/**
+ * etchvtor_int16_element_validator()
+ * element_validator override for int16 validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_int16_element_validator(etch_validator* vtor)
+{
+ return etchvtor_int16_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_int16()
+ * constructor for int16 validator
+ */
+etch_validator* new_validator_int16(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "int16[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_INT16, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_INT16, 0, CLASSID_ARRAY_INT16, numdimensions, name);
+
+ newvtor->validate = etchvtor_int16_validate;
+ newvtor->check_value = etchvtor_int16_check_value;
+ newvtor->validate_value = etchvtor_int16_validate_value;
+ newvtor->element_validator = etchvtor_int16_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * int32 validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_int32 /* int32 validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_INT32 * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_int32_get()
+ * get a int32 validator for specified dimensions
+ */
+etch_validator* etchvtor_int32_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_int32(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_int32[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_int32(ndims), etchvtor_cache_int32);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_int32_validate()
+ * validate() override verifying value is in range of int
+ */
+int etchvtor_int32_validate(etch_validator* vtor, etch_object* value)
+{
+ int result = -1;
+ if (vtor->numdimensions > 0)
+ result = etch_typevtor_validate(vtor, value);
+ else
+ if (NULL == value)
+ result = -1;
+ else switch(value->class_id)
+ { case CLASSID_PRIMITIVE_BYTE:
+ case CLASSID_PRIMITIVE_INT8:
+ case CLASSID_PRIMITIVE_INT16:
+ case CLASSID_PRIMITIVE_INT32:
+ result = 0;
+ break;
+ case CLASSID_PRIMITIVE_INT64:
+ if (is_inrange_int32(((etch_int64*)value)->value))
+ result = 0;
+ }
+
+ return result;
+}
+
+
+/**
+ * etchvtor_int32_validate_value()
+ * validate_value override for int validator
+ */
+etch_object* etchvtor_int32_validate_value(etch_validator* vtor, etch_object* value)
+{
+ int intval = 0;
+
+ etch_object* valobj = etch_typevtor_validate_value(vtor, value);
+ if (NULL == valobj) return NULL;
+
+ /* here, the returned object is the passed object, caller does no cleanup */
+ if (vtor->numdimensions > 0 || is_etch_int32(value)) return value;
+
+ if (-1 == etchtagdata_int32_value (value, &intval)) return NULL;
+
+ /* here, the returned object is not the same as the passed object,
+ * so caller must replace the reference, and destroy the passed object */
+ return (etch_object*) new_int32(intval);
+}
+
+
+/**
+ * etchvtor_int32_element_validator()
+ * element_validator override for int32 validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_int32_element_validator(etch_validator* vtor)
+{
+ return etchvtor_int32_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * etchvtor_int32_check_value()
+ * check_value override for int32 validator
+ * returns external type of specified value
+ */
+int etchvtor_int32_check_value(etch_validator* vtor, etch_object* value, byte* typecode_out)
+{
+ int intval = 0;
+
+ int result = vtor->validate(vtor, value);
+ if (-1 == result);
+ else
+ if (vtor->numdimensions)
+ *typecode_out = ETCH_XTRNL_TYPECODE_ARRAY;
+ else
+ if (-1 == (result = etchtagdata_int32_value(value, &intval)));
+ else
+ if (is_inrange_byte(intval))
+ *typecode_out = ETCH_XTRNL_TYPECODE_BYTE;
+ else
+ if (is_inrange_int16(intval))
+ *typecode_out = ETCH_XTRNL_TYPECODE_SHORT;
+ else *typecode_out = ETCH_XTRNL_TYPECODE_INT;
+
+ return result;
+}
+
+
+/**
+ * new_validator_int32()
+ * constructor for int32 validator
+ */
+etch_validator* new_validator_int32(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "int32[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_INT32, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_INT32, 0, CLASSID_ARRAY_INT32, numdimensions, name);
+
+ newvtor->validate = etchvtor_int32_validate;
+ newvtor->check_value = etchvtor_int32_check_value;
+ newvtor->validate_value = etchvtor_int32_validate_value;
+ newvtor->element_validator = etchvtor_int32_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * int64 validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_int64 /* int64 validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_INT64 * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_int64_get()
+ * get a int64 validator for specified dimensions
+ */
+etch_validator* etchvtor_int64_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_int64(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_int64[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_int64(ndims), etchvtor_cache_int64);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_int64_validate()
+ * validate() override verifying value is in range of long long
+ */
+int etchvtor_int64_validate(etch_validator* vtor, etch_object* value)
+{
+ int result = -1;
+
+ if (vtor->numdimensions > 0)
+ result = etch_typevtor_validate(vtor, value);
+ else
+ if (NULL == value);
+ else switch(value->class_id)
+ { case CLASSID_PRIMITIVE_BYTE:
+ case CLASSID_PRIMITIVE_INT8:
+ case CLASSID_PRIMITIVE_INT16:
+ case CLASSID_PRIMITIVE_INT32:
+ case CLASSID_PRIMITIVE_INT64:
+ result = 0;
+ }
+ return result;
+}
+
+
+/**
+ * etchvtor_int64_validate_value()
+ * validate_value override for long validator
+ */
+etch_object* etchvtor_int64_validate_value(etch_validator* vtor, etch_object* value)
+{
+ int64 longval = 0;
+
+ etch_object* valobj = etch_typevtor_validate_value(vtor, value);
+ if (NULL == valobj) return NULL;
+
+ /* here, the returned object is the passed object, caller does no cleanup */
+ if (vtor->numdimensions > 0 || is_etch_int64(value)) return value;
+
+ if (-1 == etchtagdata_int64_value (value, &longval)) return NULL;
+
+ /* here, the returned object is not the same as the passed object,
+ * so caller must replace the reference, and destroy the passed object */
+ return (etch_object*) new_int64(longval);
+}
+
+
+/**
+ * etchvtor_int64_element_validator()
+ * element_validator override for int64 validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_int64_element_validator(etch_validator* vtor)
+{
+ return etchvtor_int64_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * etchvtor_int64_check_value()
+ * check_value override for int64 validator
+ * returns external type of specified value
+ */
+int etchvtor_int64_check_value(etch_validator* vtor, etch_object* value, byte* typecode_out)
+{
+ int64 longval = 0;
+
+ int result = vtor->validate(vtor, value);
+ if (-1 == result);
+ else
+ if (vtor->numdimensions)
+ *typecode_out = ETCH_XTRNL_TYPECODE_ARRAY;
+ else
+ if (-1 == (result = etchtagdata_int64_value(value, &longval)));
+ else
+ if (is_inrange_byte(longval))
+ *typecode_out = ETCH_XTRNL_TYPECODE_BYTE;
+ else
+ if (is_inrange_int16(longval))
+ *typecode_out = ETCH_XTRNL_TYPECODE_SHORT;
+ else
+ if (is_inrange_int32(longval))
+ *typecode_out = ETCH_XTRNL_TYPECODE_INT;
+ else *typecode_out = ETCH_XTRNL_TYPECODE_LONG;
+
+ return result;
+}
+
+
+/**
+ * new_validator_int64()
+ * constructor for int64 validator
+ */
+etch_validator* new_validator_int64(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "int64[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_INT64, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_INT64, 0, CLASSID_ARRAY_INT64, numdimensions, name);
+
+ newvtor->validate = etchvtor_int64_validate;
+ newvtor->check_value = etchvtor_int64_check_value;
+ newvtor->validate_value = etchvtor_int64_validate_value;
+ newvtor->element_validator = etchvtor_int64_element_validator;
+
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * float validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_float /* float validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_FLOAT * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_float_get()
+ * get a float validator for specified dimensions
+ */
+etch_validator* etchvtor_float_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_float(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_float[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_float(ndims), etchvtor_cache_float);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_float_check_value()
+ * check_value override for float validator
+ * returns external type of specified value
+ */
+int etchvtor_float_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, value)) return -1;
+ *typecode_out = (vtor->numdimensions)?
+ ETCH_XTRNL_TYPECODE_ARRAY: ETCH_XTRNL_TYPECODE_FLOAT;
+ return 0;
+}
+
+
+/**
+ * etchvtor_float_element_validator()
+ * element_validator override for float validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_float_element_validator(etch_validator* vtor)
+{
+ return etchvtor_float_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_float()
+ * constructor for float validator
+ */
+etch_validator* new_validator_float(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "float[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_FLOAT, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_FLOAT, 0, CLASSID_ARRAY_FLOAT, numdimensions, name);
+
+ newvtor->check_value = etchvtor_float_check_value;
+ newvtor->element_validator = etchvtor_float_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * double validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_double /* double validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_DOUBLE * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_double_get()
+ * get a double validator for specified dimensions
+ */
+etch_validator* etchvtor_double_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_double(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_double[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_double(ndims), etchvtor_cache_double);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_double_check_value()
+ * check_value override for double validator
+ * returns external type of specified value
+ */
+int etchvtor_double_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, value)) return -1;
+
+ *typecode_out = (vtor->numdimensions)?
+ ETCH_XTRNL_TYPECODE_ARRAY: ETCH_XTRNL_TYPECODE_DOUBLE;
+ return 0;
+}
+
+
+/**
+ * etchvtor_double_element_validator()
+ * element_validator override for double validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_double_element_validator(etch_validator* vtor)
+{
+ return etchvtor_double_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_double()
+ * constructor for double validator
+ */
+etch_validator* new_validator_double(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "double[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_DOUBLE, ETCHTYPEB_PRIMITIVE,
+ CLASSID_PRIMITIVE_DOUBLE, 0, CLASSID_ARRAY_DOUBLE, numdimensions, name);
+
+ newvtor->check_value = etchvtor_double_check_value;
+ newvtor->element_validator = etchvtor_double_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * string validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_string /* string validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_STRING * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_string_get()
+ * get a string validator for specified dimensions
+ */
+etch_validator* etchvtor_string_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_string(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_string[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_string(ndims), etchvtor_cache_string);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_string_check_value()
+ * check_value override for string validator
+ * returns external type of specified value
+ */
+int etchvtor_string_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ byte typecode = 0;
+ if (-1 == vtor->validate(vtor, value)) return -1;
+
+ if (vtor->numdimensions)
+ typecode = ETCH_XTRNL_TYPECODE_ARRAY;
+ else
+ if (((etch_string*)value)->char_count)
+ typecode = ETCH_XTRNL_TYPECODE_STRING;
+ else typecode = ETCH_XTRNL_TYPECODE_EMPTY_STRING;
+
+ if (typecode) *typecode_out = typecode;
+ return 0;
+}
+
+
+/**
+ * etchvtor_string_element_validator()
+ * element_validator override for string validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_string_element_validator(etch_validator* vtor)
+{
+ return etchvtor_string_get(vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_string()
+ * constructor for string validator
+ */
+etch_validator* new_validator_string(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "string[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_STRING, ETCHTYPEB_PRIMITIVE,
+ CLASSID_STRING, 0, CLASSID_ARRAY_STRING, numdimensions, name);
+
+ newvtor->check_value = etchvtor_string_check_value;
+ newvtor->element_validator = etchvtor_string_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * object validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_object /* object validator cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_OBJECT * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_object_get()
+ * get a object validator for specified dimensions
+ */
+etch_validator* etchvtor_object_get(const int ndims)
+{
+ etch_validator* vtor = NULL;
+ if (-1 == etchvtor_check_dimensions(ndims)) return NULL;
+
+ if (ndims >= ETCHVTOR_MAX_CACHED)
+ vtor = new_validator_object(ndims);
+ else
+ if (NULL == (vtor = etchvtor_cache_object[ndims]))
+ vtor = etchvtor_cache_validator(
+ new_validator_object(ndims), etchvtor_cache_object);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_object_validate()
+ * any etch c object can be assigned to a scalar etch c object.
+ * this validation is necessary in the c code whereas it is not in the java version.
+ */
+int etchvtor_object_validate(etch_validator* vtor, etch_object* value)
+{
+ return value? 0: -1;
+}
+
+
+/**
+ * etchvtor_object_check_value()
+ * check_value override for object validator
+ * returns external type of specified value
+ */
+int etchvtor_object_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, value)) return -1;
+
+ if (vtor->numdimensions)
+ *typecode_out = ETCH_XTRNL_TYPECODE_ARRAY;
+ else *typecode_out = ETCH_XTRNL_TYPECODE_ANY;
+
+ return 0;
+}
+
+
+/**
+ * etchvtor_object_element_validator()
+ * element_validator override for object validator
+ * gets validator for array element or scalar
+ */
+etch_validator* etchvtor_object_element_validator(etch_validator* vtor)
+{
+ return vtor->numdimensions? etchvtor_object_get(vtor->numdimensions - 1): vtor;
+}
+
+
+/**
+ * new_validator_object()
+ * constructor for object validator
+ */
+etch_validator* new_validator_object(const int numdimensions)
+{
+ etch_validator* newvtor = NULL;
+ static char* mask = "object[%d]"; char name[20];
+ sprintf(name,mask,numdimensions);
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_OBJECT, ETCHTYPEB_ETCHOBJECT,
+ CLASSID_OBJECT, 0, CLASSID_ARRAY_OBJECT, numdimensions, name);
+
+ newvtor->validate = etchvtor_object_validate;
+ newvtor->check_value = etchvtor_object_check_value;
+ newvtor->element_validator = etchvtor_object_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * exception validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_exception /* exception vtor cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_EXCEPTION * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_exception_get()
+ * get an exception validator
+ */
+etch_validator* etchvtor_exception_get()
+{
+ etch_validator* vtor = NULL;
+
+ if (NULL == (vtor = etchvtor_cache_exception[0]))
+ vtor = etchvtor_cache_validator(
+ new_validator_exception(), etchvtor_cache_exception);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_exception_check_value()
+ * check_value override for exception validator
+ * returns external type of specified value
+ */
+int etchvtor_exception_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, (etch_object*) value)) return -1;
+ *typecode_out = ETCH_XTRNL_TYPECODE_CUSTOM;
+ return 0;
+}
+
+
+/**
+ * etchvtor_exception_element_validator()
+ */
+etch_validator* etchvtor_exception_element_validator(etch_validator* vtor)
+{
+ return etchvtor_exception_get(0);
+}
+
+
+/**
+ * new_validator_exception()
+ * constructor for exception validator
+ */
+etch_validator* new_validator_exception(const int numdimensions)
+{
+ etch_validator* newvtor = new_type_validator_1(CLASSID_VALIDATOR_EXCEPTION,
+ ETCHTYPEB_EXCEPTION, CLASSID_EXCEPTION, 0, CLASSID_ARRAY_OBJECT, 0, "excp");
+ newvtor->check_value = etchvtor_exception_check_value;
+ newvtor->element_validator = etchvtor_exception_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * eod object validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+etch_validator** etchvtor_cache_eod /* eod vtor cache address */
+ = &etchvtor_cache[ETCHVTOR_CACHE_SLOT_EOD * ETCHVTOR_MAX_CACHED];
+
+/**
+ * etchvtor_eod_get()
+ * get an eod object validator
+ */
+etch_validator* etchvtor_eod_get()
+{
+ etch_validator* vtor = NULL;
+
+ if (NULL == (vtor = etchvtor_cache_eod[0]))
+ vtor = etchvtor_cache_validator(
+ new_validator_eod(), etchvtor_cache_eod);
+ return vtor;
+}
+
+
+/**
+ * etchvtor_eod_validate()
+ * validate() override
+ */
+int etchvtor_eod_validate(etch_validator* vtor, etch_object* value)
+{
+ return etchtagdata_is_eod(value)? 0: -1;
+}
+
+
+/**
+ * new_validator_eod()
+ * constructor for eod validator
+ */
+etch_validator* new_validator_eod(const int numdimensions)
+{
+ etch_validator* newvtor = new_type_validator_1(CLASSID_VALIDATOR_EOD,
+ ETCHTYPEB_NONE, CLASSID_NONE, 0, CLASSID_NONE, 0, "eod");
+ newvtor->validate = etchvtor_eod_validate;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * struct validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * etchvtor_struct_get()
+ * get a struct validator
+ */
+etch_validator* etchvtor_struct_get(etch_type* type, const int numdims)
+{
+ etch_validator* vtor = new_validator_struct(type, numdims);
+ /* caller must free this validator since is_cached is false */
+ return vtor;
+}
+
+
+/**
+ * etchvtor_struct_validate()
+ * validate() override verifying value is struct of expected type
+ */
+int etchvtor_struct_validate(etch_validator* vtor, etch_object* value)
+{
+ int result = etch_typevtor_validate(vtor, value);
+ if (result == -1);
+ else
+ if (vtor->numdimensions)
+ if (is_etch_nativearray(value));
+ else result = -1;
+ else
+ if (is_etch_struct(value))
+ if (is_equal_types(vtor->struct_type,
+ ((etch_structvalue*)value)->struct_type));
+ else result = -1;
+ else result = -1;
+
+ return result;
+}
+
+
+/**
+ * etchvtor_struct_check_value()
+ * check_value override for struct validator
+ * returns external type of specified value
+ */
+int etchvtor_struct_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, (etch_object*) value)) return -1;
+ *typecode_out = vtor->numdimensions?
+ ETCH_XTRNL_TYPECODE_ARRAY: ETCH_XTRNL_TYPECODE_CUSTOM;
+ return 0;
+}
+
+
+/**
+ * etchvtor_struct_element_validator()
+ */
+etch_validator* etchvtor_struct_element_validator(etch_validator* vtor)
+{
+ return etchvtor_struct_get(vtor->struct_type, vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_struct()
+ * constructor for struct validator
+ */
+etch_validator* new_validator_struct (etch_type* type, const int numdimensions)
+{
+ char namebuf[64] = "struct_", ascbuf[64], dimbuf[8], *abuf = ascbuf;
+ etch_validator* newvtor = NULL;
+ if (!type || !is_good_type(type)) return NULL;
+ etch_unicode_to_ansi(&abuf, type->name); /* todo change id_name to ascii */
+ strcat(namebuf, abuf); strcat(namebuf, "[");
+ sprintf(dimbuf, etchgc.pctd, numdimensions);
+ strcat(namebuf, dimbuf); strcat(namebuf, "]");
+ etch_free(abuf); /* todo change id_name to ascii */
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_STRUCT, ETCHTYPEB_STRUCTVAL,
+ CLASSID_STRUCTVALUE, 0, CLASSID_ARRAY_OBJECT, numdimensions, namebuf);
+
+ newvtor->struct_type = type;
+
+ newvtor->validate = etchvtor_struct_validate;
+ newvtor->check_value = etchvtor_struct_check_value;
+ newvtor->element_validator = etchvtor_struct_element_validator;
+ return newvtor;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * custom validator
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * etchvtor_custom_get()
+ * get a custom validator
+ */
+etch_validator* etchvtor_custom_get (const unsigned short obj_type,
+ const unsigned short class_id, etch_type* type, const int numdims)
+{
+ etch_validator* vtor = new_validator_custom (obj_type, class_id, type, numdims);
+ /* caller must free this validator since is_cached is false */
+ return vtor;
+}
+
+
+/**
+ * etchvtor_custom_validate()
+ * validate() override verifying value is of expected type
+ */
+int etchvtor_custom_validate (etch_validator* vtor, etch_object* value)
+{
+ int result = etch_typevtor_validate(vtor, value);
+
+ return result;
+}
+
+
+/**
+ * etchvtor_struct_check_value()
+ * check_value override for struct validator
+ * returns external type of specified value.
+ */
+int etchvtor_custom_check_value(etch_validator* vtor,
+ etch_object* value, byte* typecode_out)
+{
+ if (-1 == vtor->validate(vtor, (etch_object*) value)) return -1;
+ *typecode_out = vtor->numdimensions?
+ ETCH_XTRNL_TYPECODE_ARRAY: ETCH_XTRNL_TYPECODE_CUSTOM;
+ return 0;
+}
+
+
+/**
+ * etchvtor_custom_element_validator()
+ */
+etch_validator* etchvtor_custom_element_validator (etch_validator* vtor)
+{
+ return etchvtor_struct_get (vtor->struct_type, vtor->numdimensions - 1);
+}
+
+
+/**
+ * new_validator_custom()
+ * constructor for custom validator
+ */
+etch_validator* new_validator_custom (const unsigned short obj_type,
+ const unsigned short class_id, etch_type* type, const int numdims)
+{
+ char namebuf[64] = "custom_", ascbuf[64], dimbuf[8], *abuf = ascbuf;
+ etch_validator* newvtor = NULL;
+ if (!type || !is_good_type(type)) return NULL;
+ etch_unicode_to_ansi(&abuf, type->name); /* todo change id_name to ascii */
+ strcat(namebuf, abuf); strcat(namebuf, "[");
+ sprintf(dimbuf, etchgc.pctd, numdims);
+ strcat(namebuf, dimbuf); strcat(namebuf, "]");
+ etch_free(abuf); /* todo change id_name to ascii */
+
+ newvtor = new_type_validator_1(CLASSID_VALIDATOR_CUSTOM, obj_type,
+ class_id, 0, CLASSID_ARRAY_OBJECT, numdims, namebuf);
+
+ newvtor->struct_type = type;
+
+ newvtor->validate = etchvtor_custom_validate;
+ newvtor->check_value = etchvtor_custom_check_value;
+ newvtor->element_validator = etchvtor_custom_element_validator;
+ return newvtor;
+}
+
+
+
+
+
+