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;
+}
+
+
+
+
+
+