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 [14/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_defvalufact.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_defvalufact.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_defvalufact.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_defvalufact.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,934 @@
+/* $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_defvalufact.c 
+ * default value factory from which all others inherit
+ */
+
+#include "etch_defvalufact.h"
+#include "etch_serializer.h"
+#include "etch_global.h"
+#include "etchutl.h"
+#include "etchmap.h"
+#include "etchlog.h"
+char* ETCHVALF = "VALF";
+
+void etchvf_instantiate_builtins();
+
+etch_type*    defvf_add_type (default_value_factory*, etch_type*);
+etch_id_name* get_idname_by_id (etch_hashtable* map, const unsigned id); 
+etch_type*    defvf_get_type_by_id (default_value_factory*,  const unsigned id);
+etch_type*    defvf_get_type_by_name(default_value_factory*, const wchar_t* name); 
+etch_type*    defvf_get_type_by_name(default_value_factory*, const wchar_t* name); 
+wchar_t*      defvf_get_string_encoding (etch_value_factory*);
+etch_type*    defvf_get_custom_struct_type (default_value_factory*, const unsigned);
+etch_int64*   defvf_get_message_id  (default_value_factory*, etch_message*);
+int           defvf_set_message_id  (default_value_factory*, etch_message*, etch_int64* id);
+etch_int64*   defvf_get_in_reply_to (default_value_factory*, etch_message*);
+int           defvf_set_in_reply_to (default_value_factory*, etch_message*, etch_int64* id);
+etch_type*    defvf_get_mt_exception(default_value_factory*);
+etch_type*    defvf_get_mt_rutime_exception(default_value_factory*);
+etch_type*    defvf_get_mt_auth_exception(default_value_factory*);
+objmask*      defvf_import_custom_value (default_value_factory*, etch_structvalue*);
+etch_structvalue* defvf_export_custom_value (default_value_factory*, objmask* value);
+etch_arraylist* new_vf_mixin_collection(default_value_factory*);
+etch_arraylist* defvf_get_types (default_value_factory*);
+int defvf_init_types(default_value_factory*, vf_idname_map*, class_to_type_map*);
+
+
+/* - - - - - - - - - - - - - - - - - - - -
+ * constructors/destructors
+ * - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * new_default_value_factory()
+ * constructor for default_value_factory
+ * @param typemap the types map. if caller supplies this object, caller
+ * retains ownership, unless vf.is_own_types flag is subsequently set false.
+ * @param c2tmap the class to type map. if caller supplies this object, caller
+ * retains ownership, unless vf.is_own_class_to_type flag is subsequently set false.
+ */
+default_value_factory* new_default_value_factory(vf_idname_map* typemap, 
+    class_to_type_map* c2tmap)
+{
+    return new_default_value_factory_a(sizeof(default_value_factory), 
+        typemap, c2tmap);
+}
+
+
+/**
+ * new_default_value_factory_a()
+ * constructor for default_value_factory
+ * @param objsize size of the object footprint in bytes. 
+ * @param typemap the types map. if caller supplies this object, caller
+ * retains ownership, unless vf.is_own_types flag is subsequently set false.
+ * @param c2tmap the class to type map. if caller supplies this object, caller
+ * retains ownership, unless vf.is_own_class_to_type flag is subsequently set false.
+ */
+default_value_factory* new_default_value_factory_a(const int objsize, 
+    vf_idname_map* typemap, class_to_type_map* c2tmap)
+{
+    i_value_factory* vtab;
+
+    default_value_factory* newvf = (default_value_factory*) new_value_factory(objsize);
+
+    newvf->destroy = destroy_default_value_factory;
+
+    vtab = newvf->vtab;
+    vtab->add_type              = defvf_add_type;
+    vtab->export_custom_value   = defvf_export_custom_value;
+    vtab->get_custom_struct_type= defvf_get_custom_struct_type;
+    vtab->get_in_reply_to       = defvf_get_in_reply_to;
+    vtab->get_message_id        = defvf_get_message_id;
+    vtab->get_string_encoding   = defvf_get_string_encoding;
+    vtab->get_type_by_id        = defvf_get_type_by_id;
+    vtab->get_type_by_name      = defvf_get_type_by_name;
+    vtab->get_types             = defvf_get_types;
+    vtab->import_custom_value   = defvf_import_custom_value;
+    vtab->set_in_reply_to       = defvf_set_in_reply_to;
+    vtab->set_message_id        = defvf_set_message_id;
+
+    defvf_init_types(newvf, typemap, c2tmap);
+
+    newvf->mixins = new_vf_mixin_collection(newvf);
+
+    return newvf;
+}
+
+
+/**
+ * destroy_default_value_factory()
+ * destructor for default_value_factory
+ */
+int destroy_default_value_factory(default_value_factory* vf)  
+{   
+    if (vf->refcount > 0 && --vf->refcount > 0) return -1;  
+
+    if (!is_etchobj_static_content(vf))
+    {   
+        if (vf->mixins)
+            vf->mixins->destroy(vf->mixins);
+
+        /* class_to_type map must be destroyed prior to types map 
+         * since class_to_type holds references to types map objects */
+        if (vf->is_own_class_to_type) 
+            vf->class_to_type->destroy(vf->class_to_type);
+
+        if (vf->is_own_types)
+            vf->types ->destroy(vf->types);  
+
+        if (vf->impl) /* inheritor's instance object */
+            vf->impl->destroy(vf->impl);
+    }
+
+   return destroy_objectex((objmask*) vf);
+}
+
+
+/**
+ * defvf_init_types()
+ * initialize a value factory object with fields and types.
+ */
+int defvf_init_types(default_value_factory* newvf,
+    vf_idname_map* typemap, class_to_type_map* c2tmap)
+{
+    etch_hashtable* c2t = NULL;
+
+    if (typemap)
+        newvf->types = typemap;
+    else
+    {   newvf->types = new_vf_types_collection(ETCH_DEFVF_IDNMAP_DEFINITSIZE);
+        newvf->is_own_types = TRUE;
+    }
+
+    if (c2tmap)
+        newvf->class_to_type = c2tmap;
+    else 
+    {   newvf->class_to_type = new_class_to_type_map(ETCH_DEVVF_C2TMAP_DEFINITSIZE);
+        newvf->is_own_class_to_type = TRUE;
+    }
+
+    etchvf_instantiate_builtins();   
+
+    defvf_add_type(newvf, builtins._mt__etch_runtime_exception);
+    defvf_add_type(newvf, builtins._mt__etch_auth_exception);
+    defvf_add_type(newvf, builtins._mt__exception);
+    defvf_add_type(newvf, builtins._mt__etch_list);
+    defvf_add_type(newvf, builtins._mt__etch_map);
+    defvf_add_type(newvf, builtins._mt__etch_set);
+    defvf_add_type(newvf, builtins._mt__etch_datetime);
+
+    c2t = newvf->class_to_type; 
+    etch_serializer_exception_init(builtins._mt__exception, c2t);
+    etch_serializer_authxcp_init  (builtins._mt__etch_auth_exception, c2t);
+    etch_serializer_rtxcp_init    (builtins._mt__etch_runtime_exception, c2t);
+    etch_serializer_list_init     (builtins._mt__etch_list,c2t);
+    etch_serializer_map_init      (builtins._mt__etch_map, c2t);
+    etch_serializer_set_init      (builtins._mt__etch_set, c2t);
+    etch_serializer_date_init     (builtins._mt__etch_datetime, c2t);
+
+    return 0;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - -
+ * vf class methods
+ * - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * defvf_add_type()
+ * adds a type to set of types
+ * @param type a non-disposable etch_type object
+ * @return the effective type. if there was a name collision, the existing type
+ * is returned in place of the supplied type, AND the supplied type is destroyed.
+ * this simplifies logic up the line, and is consistent with caller expecting to
+ * relinquish memory management of the type passed.
+ */
+etch_type* defvf_add_type (default_value_factory* vf, etch_type* type) 
+{
+    etch_type *effective_type = type;
+
+    const int result = vf->types->vtab->inserth
+        (vf->types->realtable, type, NULL, vf->types, 0); 
+
+    if (-1 == result)
+        effective_type = defvf_get_type_by_name(vf, type->name);
+
+    if (effective_type != type && NULL != effective_type)
+        destroy_static_type(type);
+
+    #ifdef ETCH_DEBUG_VF
+    if  (effective_type) 
+         wprintf(L"add type %08x '%s'\n", 
+            (size_t) (void*) effective_type, effective_type->name);
+    else wprintf(L"error adding type '%s'\n", type->name);
+    #endif
+
+    return effective_type;   
+}
+
+
+/**
+ * get_idname_by_id()
+ * given a id_name map and a numeric id, return the id_name for that key. 
+ * @return a non-disposable *reference*, not a copy, or null if not found.
+ */
+etch_id_name* get_idname_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;
+}
+
+
+/**
+ * defvf_get_type_by_id()
+ * @return a non-disposable reference to the type matching the supplied id,
+ * or null if no match. all mixed-in vfs are recursed for a match.
+ */
+etch_type* defvf_get_type_by_id (default_value_factory* vf, const unsigned id)
+{
+    etch_type* type = get_idname_by_id(vf->types, id);
+    if (type) return type;
+
+    if (vf->mixins->count) 
+    {
+        etch_iterator iterator; 
+        set_iterator(&iterator, vf->mixins, &vf->mixins->iterable);
+ 
+        while(iterator.has_next(&iterator))
+        {
+            default_value_factory* mvf 
+                = (default_value_factory*) iterator.current_value;
+
+            if (is_etch_valuefact(mvf) && (mvf != vf))
+            {
+                type = defvf_get_type_by_id(mvf, id);
+                if (type) return type; 
+            }
+
+            iterator.next(&iterator);
+        }
+    }
+
+    return NULL;
+}
+
+
+/**
+ * get_idname_by_name()
+ * given a id_name map and a name string, return the id_name for that name. 
+ * @return a non-disposable *reference*, not a copy, or null if not found.
+ * recall that etch_type and etch_field each are typedefs of etch_id_name. 
+ */
+etch_id_name* get_idname_by_name(etch_hashtable* map, const wchar_t* name)
+{
+    etch_hashitem  hashbucket, *thisitem = &hashbucket; 
+    const unsigned hash = etch_get_wchar_hashkey(name);
+  
+    const int result = map->vtab->findh(map->realtable, hash, map, &thisitem); 
+ 
+    return result == 0? (etch_id_name*) thisitem->key: NULL;
+}
+
+
+/**
+ * etchtypemap_get_by_name()
+ * given a type map and a name, looks up the type matching that name, 
+ * adding a new type to the map if no match was found.
+ * @return a non-disposable reference to the type matching the supplied  
+ * name, or null if no match.  
+ */
+etch_type* etchtypemap_get_by_name(etch_hashtable* map, const wchar_t* name)
+{
+    etch_type* thistype = get_idname_by_name(map, name);
+
+    if (NULL == thistype) 
+    {
+        int result = map->vtab->inserth(map->realtable, 
+            thistype = new_type(name), NULL, map, 0); 
+    }
+       
+    return thistype;
+}
+
+
+/**
+ * defvf_get_type_by_name()
+ * searches vf and all mixed-in vfs for type matching specified name.
+ * @return a non-disposable reference to the type corresponding to 
+ * specified name, or null if no match.
+ */
+etch_type* defvf_get_type_by_name (default_value_factory* vf, const wchar_t* name) 
+{
+    etch_type* type = get_idname_by_name(vf->types, name);
+    if (type) return type;
+
+    if (vf->mixins->count) 
+    {
+        etch_iterator iterator; 
+        set_iterator(&iterator, vf->mixins, &vf->mixins->iterable);
+ 
+        while(iterator.has_next(&iterator))
+        {
+            default_value_factory* mvf 
+                = (default_value_factory*) iterator.current_value;
+
+            if (is_etch_valuefact(mvf) && (mvf != vf)) 
+            {
+                type = defvf_get_type_by_name(mvf, name);
+                if (type) return type; 
+            }
+
+            iterator.next(&iterator);
+        }
+    }
+
+    return NULL;
+}
+
+	
+/**
+ * defvf_get_types()
+ * @return a disposable arraylist of non-disposable references to all types 
+ * resident in this vf, and in all its mixed-in vfs. caller should invoke 
+ * the returned list's destructor, which will destroy the list shell.
+ */
+etch_arraylist* defvf_get_types (default_value_factory* vf)
+{    
+    etch_arraylist* typeslist = get_map_keys(vf->types);
+
+    if (vf->mixins->count) 
+    {
+        int  newmixintypes = 0;
+        etch_iterator iterator; 
+        set_iterator(&iterator, vf->mixins, &vf->mixins->iterable);
+ 
+        while(iterator.has_next(&iterator))
+        {
+            etch_arraylist* mvflist;
+ 
+            default_value_factory* mvf 
+                = (default_value_factory*) iterator.current_value;
+
+            if (is_etch_valuefact(mvf) && (mvf != vf)) 
+            {
+                mvflist = get_map_keys(mvf->types);
+
+                newmixintypes += arraylist_add_from
+                    (typeslist, mvflist, etchtypelist_comparator); 
+                    
+                mvflist->destroy(mvflist);
+            }
+
+            iterator.next(&iterator);
+        }
+    }
+
+    return typeslist; /* caller must dispose */
+}
+
+
+/**
+ * defvf_get_string_encoding()
+ * @returns a non-disposable reference to the encoding type
+ */
+wchar_t* defvf_get_string_encoding (etch_value_factory* vf)
+{
+    return (wchar_t*) str_utf8;
+}
+
+
+/**
+ * get_etch_string_encoding()
+ * return etch code indicating current string encoding
+ */
+int get_etch_string_encoding(etch_value_factory* vf)
+{
+    wchar_t* encoding = vf->vtab->get_string_encoding(vf);
+    if (0 == wcscmp(encoding, L"utf-8"))  return ETCH_ENCODING_UTF8; 
+    if (0 == wcscmp(encoding, L"utf-16")) return ETCH_ENCODING_UTF16;
+    return ETCH_ENCODING_ASCII;     
+} 
+
+
+/**
+ * defvf_get_custom_struct_type()
+ * @return a non-disposable reference to the etch type type corresponding   
+ * to the specified class. invoked recursively via mixed in vfs. 
+ */
+etch_type* defvf_get_custom_struct_type(default_value_factory* vf, 
+    const unsigned etchclass)
+{
+    etch_type* type = (etch_type*) etchmap_find(vf->class_to_type, etchclass, 0);
+    if (type) return type;
+
+    if (vf->mixins->count) 
+    {
+        etch_iterator iterator; 
+        set_iterator(&iterator, vf->mixins, &vf->mixins->iterable);
+ 
+        while(iterator.has_next(&iterator))
+        {
+            default_value_factory* mvf 
+                = (default_value_factory*) iterator.current_value;
+                  
+            if (is_etch_valuefact(mvf) && (mvf != vf)) /* ensure no cycle */
+            {
+                type = mvf->vtab->get_custom_struct_type(mvf, etchclass);
+                if (type) break;
+            }
+
+            iterator.next(&iterator);
+        }
+    }
+
+    return type;
+}
+	
+
+/**
+ * defvf_import_custom_value()
+ * get helper method from the struct's type to import the custom value associated
+ * with the type. if found, invoke the method to create the custom object.
+ * @param sv the *disposable* raw key-value pairs read in by tdi,
+ * from which to reconstruct the expected custom value object.
+ * caller relinquishes ownership of this object regardless of outcome.
+ * @return the *disposable* custom object, which must be cast by caller, or null.
+ */
+objmask* defvf_import_custom_value (default_value_factory* vf, etch_structvalue* sv)
+{  
+    objmask* custom_value = NULL;
+
+    etch_serializer* impxhelper = etchtype_get_impexphelper(sv->struct_type);
+   
+    if (impxhelper)
+        custom_value = impxhelper->import_value(impxhelper, (objmask*) sv);
+     
+    sv->destroy(sv);
+
+    return custom_value;
+}
+
+
+/**
+ * defvf_export_custom_value()
+ * establishes the etch type of the custom struct to be exported to, gets the
+ * export helper method from the type, and invokes that method to do the export.
+ * @param value the custom value object to be exported to a struct for tdo.
+ * caller retains ownership of this object.
+ * @return the exported struct, or null. caller owns the returned struct.
+ */
+etch_structvalue* defvf_export_custom_value(default_value_factory* vf, objmask* value)
+{
+    etch_type* custom_type = NULL;
+    etch_serializer*  impxhelper = NULL; 
+    etch_structvalue* exported_value = NULL;
+    if (NULL == value) return NULL;
+
+    custom_type = defvf_get_custom_struct_type(vf, ETCHOBJCLASS(value));
+
+    if (NULL == custom_type)
+    {
+        switch(value->obj_type)
+        { 
+          case ETCHTYPEB_STRUCTVAL:
+               custom_type = ((etch_structvalue*)value)->struct_type;
+               break;
+          case ETCHTYPEB_EXCEPTION:
+               custom_type = builtins._mt__etch_runtime_exception;
+               break;
+          case ETCHTYPEB_ETCHLIST:
+               custom_type = builtins._mt__etch_list;
+               break;
+          case ETCHTYPEB_ETCHMAP:
+               custom_type = builtins._mt__etch_map;
+               break;
+          case ETCHTYPEB_ETCHSET:
+               custom_type = builtins._mt__etch_set;
+               break;
+        }
+    }
+
+    /* fetch non-disposable helper object from custom type */
+    impxhelper = etchtype_get_impexphelper(custom_type);
+
+    if (impxhelper && value)
+    {   /* export value object to struct */
+        exported_value = (etch_structvalue*) 
+            impxhelper->export_value(impxhelper, value);
+
+        /* changed to not destroy value 6/23, since the tdo itself does not own 
+         * the value, and the export custom value is invoked from tdo write_value. */
+        /* value->destroy(value); */
+    }
+
+    return exported_value;
+}
+
+
+/**
+ * defvf_add_mixin()
+ * add a mixed in value factory to this value factory.
+ * @return 0 or -1.
+ */
+int defvf_add_mixin(default_value_factory* vf, etch_value_factory* mixedin_vf)
+{
+    return arraylist_add(vf->mixins, mixedin_vf);
+}
+
+
+/**
+ * defvf_get_message_id()
+ * valuefactory.get_message_id() implementation.
+ * @return a non-disposable reference to the etch_int64 id object, or null. 
+ */
+etch_int64* defvf_get_message_id (default_value_factory* vf, etch_message* msg)
+{
+    return (etch_int64*) message_get(msg, builtins._mf__message_id);
+}
+
+
+/**
+ * message_get_id32()
+ * get and return message id in 32 bits. used for debugging, logging, etc.
+ */
+unsigned message_get_id32 (etch_message* msg)
+{
+    default_value_factory* vf = (default_value_factory*) msg->vf;
+    etch_int64* id64 = (etch_int64*) message_get (msg, builtins._mf__message_id);
+    const int id32 = id64? (unsigned) id64->value: 0;
+    return id32;
+}
+
+
+/**
+ * defvf_set_message_id()
+ * valuefactory.set_message_id() implementation.
+ * @param id a *disposable* etch_int64* wrapping the message id. 
+ * regardless of outcome, caller relinquishes ownership of this object.
+ * @return 0 or -1.
+ */
+int defvf_set_message_id (default_value_factory* vf, etch_message* msg, etch_int64* id)
+{
+    return message_put(msg, clone_field(builtins._mf__message_id), (objmask*) id); 
+}
+
+
+/**
+ * defvf_get_in_reply_to() 
+ * gets the id of the message to which this message is a reply.
+ * returns a non-disposable reference to an etch_int64*, not a copy, or null.
+ */
+etch_int64* defvf_get_in_reply_to (default_value_factory* vf, etch_message* msg)
+{
+    return (etch_int64*) message_get(msg, builtins._mf__in_reply_to);
+}
+
+
+/**
+ * defvf_set_in_reply_to() 
+ * sets the id of the message to which this message is a reply.
+ * @param id a *disposable* etch_int64* wrapping the message id.  
+ * regardless of outcome, caller relinquishes ownership of this object.
+ * @return 0 or -1.
+ */
+int defvf_set_in_reply_to (default_value_factory* vf, etch_message* msg, etch_int64* id)
+{
+    return message_put (msg, clone_field(builtins._mf__in_reply_to), (objmask*) id); 
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - -
+ * vf types collection
+ * - - - - - - - - - - - - - - - - - - - -
+ */
+
+/* 
+ * defvf_typescollection_clear_handler()
+ * callback set to handle freeing of key memory during a clear() of the vf
+ * types collection. such a map owns its content, which consists of both builtin
+ * types, which are marked static, and of user types, which are generally not
+ * marked static. the type's destructor is invoked here; however the destructor
+ * will take no action on the static types (these being freed later when the 
+ * builtins are destroyed. those types which are added as a result of a runtime
+ * get() call, e.g., etchtypemap_get_by_name(vf->types, L"my_newtype"),
+ * are not marked static and so will be destroyed with this map.
+ */
+int defvf_typescollection_clear_handler (objmask* key, objmask* value)  
+{
+    #if(0)
+    etch_type* type = (etch_type*) key;
+    if  (is_etchobj_static_shell(type))     
+         wprintf(L"vf types map NOT destroying %s\n", type->name);
+    else wprintf(L"vf types map destroying %s\n", type->name);
+    fflush(stdout);  
+    #endif
+
+    key->destroy(key); /* see comments above re static and nonstatic types */
+    return TRUE; 
+}
+ 
+
+/**
+ * new_vf_types_collection()
+ * return a hashtable configured as expected for a set of types 
+ */
+etch_set* new_vf_types_collection(const int initialsize)
+{
+    etch_set* map = new_set(initialsize);  
+    map->content_obj_type = ETCHTYPEB_TYPE;
+    map->content_class_id = CLASSID_ID_TYPE;  
+    map->freehook = defvf_typescollection_clear_handler;  
+    return map;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - -
+ * vf_idname_map
+ * - - - - - - - - - - - - - - - - - - - -
+ */
+
+/* 
+ * defvf_idnmap_clear_handler()
+ * callback set to handle freeing of key memory during a clear() of a vf
+ * id_name map. map keys are etch_field owned by the map. however the map does
+ * not know how to destroy such a key so we handle that here. values in this
+ * map are etch_type owned elsewhere (presumably quasi-static built-in types).
+ */
+int defvf_idnmap_clear_handler (objmask* key, objmask* value)  
+{
+    #ifdef ETCH_DEBUG_VF
+    etch_id_name* idn = (etch_id_name*) key;
+    wprintf(L"destroy idn %08x '%s'\n", (size_t) (void*) key, idn->name);
+    #endif
+ 
+    key->destroy(key);
+    return TRUE; 
+}
+ 
+
+/**
+ * new_vf_idname_map()
+ * return a hashtable configured as expected for a vf 
+ * todo lose this method and the clear handler we don't use it 
+ */
+etch_hashtable* new_vf_idname_map(const int initialsize)
+{
+    etch_hashtable* map = new_hashtable(initialsize);  
+    map->is_tracked_memory  = TRUE; 
+    map->is_readonly_keys   = FALSE; /* keys are etch_field* owned by the map */ 
+    map->is_readonly_values = FALSE; /* values are etch_type* owned elsewhere */ 
+    map->content_type       = ETCHHASHTABLE_CONTENT_OBJECT;
+    map->content_obj_type   = ETCHTYPEB_TYPE;
+    map->content_class_id   = CLASSID_ID_TYPE;  
+    map->freehook = defvf_idnmap_clear_handler; /* key memory free hook */
+    return map;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - -
+ * class_to_type_map
+ * - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * class_to_type_map_put()
+ * put the specified type to the supplied map, keyed by specified class.
+ * the map does not own the specified type object.
+ * @return 0 or -1;
+ */
+int class_to_type_map_put(class_to_type_map* map, const unsigned thisclass, 
+    etch_type* type)
+{
+    int hashvalue = etchmap_insert (map, thisclass, type, TRUE);
+    return hashvalue? 0: -1;
+}
+
+
+/**
+ * class_to_type_map_get()
+ * get the type associated with the specified class from the supplied map.
+ * @return a non-disposable reference to the matching type, or null.
+ */
+etch_type* class_to_type_map_get(class_to_type_map* map, const unsigned thisclass) 
+{
+    etch_type* foundobj = (etch_type*) etchmap_find (map, thisclass, NULL);
+    return foundobj;
+}
+
+
+/**
+ * new_class_to_type_map()
+ * class_to_type_map constructor.
+ * such a map associates a "class", which in this context is a 32-bit unsigned
+ * integer whose high 16 bits is the etch object obj_type, and the low 16 bits
+ * the etch object class_id, to an etch_type. 
+ */
+class_to_type_map* new_class_to_type_map(const int initialsize)
+{
+    /* this map calls no etch destructors when destroyed. the key strings are 
+     * freed automatically by the etch_hashtable, and the values are pointers
+     * to etch_type objects owned elsewhere. it obviously follows that this 
+     * map should be destroyed prior to any such referenced type object. 
+     */
+    class_to_type_map* map  = new_hashtable(initialsize);  
+    map->is_tracked_memory  = TRUE; 
+    map->is_readonly_keys   = TRUE; /* keys are strings owned by the hashtable */ 
+    map->is_readonly_values = TRUE; /* values are non-disposable etch_type* */ 
+    map->content_type       = ETCHHASHTABLE_CONTENT_OBJECT;
+    map->content_obj_type   = ETCHTYPEB_TYPE;
+    map->content_class_id   = CLASSID_ID_TYPE;  
+    return map;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - -
+ * built-in (etch-global, quasi-static) objects
+ * - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/* these objects are global to all vfs.
+ * for each such object, a corresponding entry should exist both in 
+ * etchvf_instantiate_builtins(), and in etchvf_free_builtins()
+ */
+const wchar_t* str_etch_runtime_exception = L"_Etch_RuntimeException";   
+const wchar_t* str_etch_auth_exception    = L"_Etch_AuthException";         
+const wchar_t* str_exception     = L"_exception"; 
+const wchar_t* str_etch_list     = L"_Etch_List"; 
+const wchar_t* str_etch_map      = L"_Etch_Map";
+const wchar_t* str_etch_set      = L"_Etch_Set";
+const wchar_t* str_etch_datetime = L"_Etch_Datetime";
+ 
+const wchar_t* str_msg           = L"msg";   
+const wchar_t* str_message_id    = L"_messageId";  
+const wchar_t* str_in_reply_to   = L"_inReplyTo";  
+const wchar_t* str_result        = L"result";
+   
+const wchar_t* str_utf8          = L"utf-8"; 
+const wchar_t* str_keys          = L"keys";    
+const wchar_t* str_values        = L"values";  
+const wchar_t* str_date_time     = L"dateTime";
+const wchar_t* str_keys_values   = L"keys_values"; 
+
+const wchar_t* str_msgizervf     = L"Messagizer.valueFactory";
+const wchar_t* str_msgizerfmt    = L"Messagizer.format";
+
+
+/* 
+ * etchvf_free_builtins()
+ * frees memory for etch-global quasi-static builtin objects,
+ * and for the validators cache and its validator content.
+ * it should be invoked at etch teardown, after last vf is destroyed.
+ * unit tests will show memory leaks unless they invoke this post-test.
+ */
+
+void etchvf_free_builtins()
+{
+    if (is_builtins_instantiated)  
+    {
+        destroy_static_type(builtins._mt__etch_runtime_exception);
+        destroy_static_type(builtins._mt__etch_auth_exception);
+        destroy_static_type(builtins._mt__exception);
+        destroy_static_type(builtins._mt__etch_list); 
+        destroy_static_type(builtins._mt__etch_map); 
+        destroy_static_type(builtins._mt__etch_set); 
+        destroy_static_type(builtins._mt__etch_datetime); 
+
+        destroy_static_field(builtins._mf_msg);
+        destroy_static_field(builtins._mf_result);
+        destroy_static_field(builtins._mf__message_id);
+        destroy_static_field(builtins._mf__in_reply_to);
+    }
+
+    etchvtor_clear_cache();  /* destroy cached validators */
+
+    is_builtins_instantiated = FALSE;
+}
+
+
+/**
+ * etchvf_instantiate_builtins()
+ * instantiate built-in objects such as default types and fields.
+ * these singleton objects are destroyed explicitly by invoking  
+ * etchvf_free_builtins().
+ * todo: mark these objects immutable and unmark in destructor.
+ * todo: determine how we handle case of multiple vfs.
+ */
+void etchvf_instantiate_builtins()
+{  
+    if (is_builtins_instantiated) return;
+
+    builtins._mt__etch_runtime_exception = new_static_type(str_etch_runtime_exception);
+    builtins._mt__etch_auth_exception = new_static_type(str_etch_auth_exception);
+    builtins._mt__exception = new_static_type(str_exception);
+    builtins._mt__etch_list = new_static_type(str_etch_list); 
+    builtins._mt__etch_map  = new_static_type(str_etch_map); 
+    builtins._mt__etch_set  = new_static_type(str_etch_set); 
+    builtins._mt__etch_datetime = new_static_type(str_etch_datetime); 
+
+    builtins._mf_msg = new_static_field(str_msg); 
+    builtins._mf_result = new_static_field(str_result); 
+    builtins._mf__message_id  = new_static_field(str_message_id); 
+    builtins._mf__in_reply_to = new_static_field(str_in_reply_to); 
+
+    etchtype_put_validator(builtins._mt__exception, 
+        clone_field(builtins._mf_result), (objmask*) etchvtor_exception_get());
+    etchtype_put_validator(builtins._mt__exception, 
+        clone_field(builtins._mf__message_id), (objmask*) etchvtor_int64_get(0));
+    etchtype_put_validator(builtins._mt__exception, 
+        clone_field(builtins._mf__in_reply_to),(objmask*) etchvtor_int64_get(0));
+
+    is_builtins_instantiated = TRUE;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - -
+ * other methods
+ * - - - - - - - - - - - - - - - - - - - -
+ */
+	
+/**
+ * etchtypelist_comparator()
+ * etch_comparator comparing two etch_types
+ * hook for arraylist_add_from to determine if a type from list b
+ * already exists in list a.
+ */
+int etchtypelist_comparator(void* a, void* b)
+{
+    return a && b && (((etch_type*)a)->id == ((etch_type*)b)->id);
+}
+
+
+/**
+ * new_vf_mixin_collection()
+ * instantiate and return a collection configured appropriately for the
+ * storage of value factory objects of mixed-in classes.
+ */
+etch_arraylist* new_vf_mixin_collection(default_value_factory* vf)
+{
+    etch_arraylist* list = new_arraylist(ETCH_DEVVF_MIXINS_DEFINITSIZE, 0);
+    list->content_type = ETCHARRAYLIST_CONTENT_OBJECT;
+    list->is_readonly  = TRUE; /* list dtor will not destroy list content */
+    list->content_obj_type = vf->obj_type;
+    list->content_class_id = vf->class_id;
+    return list;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * serializable exception tossing  
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */	
+
+  
+/**
+ * message_throw()
+ * instantiate a serializable exception object from the exception indicated by
+ * the specified parameters, and add that exception to the specified message.
+ * @param msg the message.
+ * @param xtype type of exception, excptype enumeration.
+ * @param xtext the exception text, caller retains.
+ * @return 0 success, -1 failure.
+ */
+int message_throw (etch_message* msg, excptype xtype, wchar_t* xtext)
+{
+    int result = 0;
+    etch_exception* excpobj = NULL;
+    if (NULL == msg) return -1;
+
+    excpobj = new_etch_exception (xtype, xtext, ETCHEXCP_COPYTEXT);
+    result  = message_put (msg, clone_field(builtins._mf_result), (objmask*) excpobj);
+    return result;
+} 
+
+
+/**
+ * message_throw_from()
+ * instantiate a serializable exception object from the exception in the 
+ * specified etch object, and add that exception to the specified message.
+ * @param msg the message.
+ * @param obj the object wrapping the exception, or which is the exception,
+ * caller retains.
+ * @return 0 success, -1 failure.
+ */
+int message_throw_from (etch_message* msg, objmask* obj)
+{
+    etchexception* x = get_exception_from (obj);
+    if (NULL == x) return NULL;
+
+    return message_throw (msg, x->excptype, x->excptext);
+}
+
+
+
+
+
+
+

Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_field.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_field.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_field.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_field.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,74 @@
+/* $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. 
+ */ 
+
+/* 
+ * field.c -- methods on the etch_field object.
+ * an etch_field is an etch_id_name representing a field of a struct or message 
+ * (i.e. a key for a value).
+ */
+#include "etch_field.h"
+
+/** 
+ * an etch_field is for now simply a typedef of etch_id_name.
+ * all its methods except ctor are #defined as those of etch_id_name.
+ */
+
+etch_field* new_field(const wchar_t* name)
+{
+    etchparentinfo* inheritlist = NULL;
+
+    etch_field* newobj = (etch_field*) new_id_name(name);
+    if (NULL == newobj) return NULL;
+    newobj->obj_type = ETCHTYPEB_FIELD;
+    newobj->class_id = CLASSID_ID_FIELD;
+
+    /* fetch cached inheritance list, or create if initial instantiation, 
+     * and ensure id_name parent keys exist in the (one-based) list */
+    inheritlist = get_vtab_inheritance_list((objmask*)newobj,
+       2, 1, CLASSID_VTAB_FIELD);
+    ETCH_ASSERT(newobj->vtab && newobj->vtab->inherits_from);
+    inheritlist[1].obj_type = newobj->obj_type;
+    inheritlist[1].class_id = CLASSID_ID_NAME;
+
+    return newobj;
+}
+
+
+/**
+ * new__static_field() 
+ * create a field object whose destructor will have no effect.
+ */
+etch_field* new_static_field(const wchar_t* name)
+{
+    etch_field* newfield = new_field(name);
+    set_etchobj_static_all(newfield);
+    return newfield;
+} 
+
+ 
+/** 
+ * destroy_static_field()
+ * etch_field destructor.
+ * this should not be set as the virtual dtor for a field, since the field
+ * would then not be quasi-static as desired. it should be invoked explicitly
+ */
+int destroy_static_field(etch_field* field)
+{
+    clear_etchobj_static_all(field);
+    return destroy_field(field); 
+} 
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_id_name.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_id_name.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_id_name.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_id_name.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,221 @@
+/* $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. 
+ */ 
+
+/*
+ * id_name.c
+ * an id_name is a base class for etch_field and etch_type, used to bind
+ * a type or field name to an associated and unique id. the id is used for
+ * certain operations, such as the key in a map, comparisons, wire encoding.
+ * it owns memory for its name, but not necessarily that for its impl.
+ * since the character name is only used internally, not on the wire, 
+ * we are gradually converting this object to use an 8-bit character 
+ * name, primarily to enable type-related logging.
+ */
+
+#include "etch_id_name.h"
+#include "etch_encoding.h"
+#include "etch_global.h"
+#include "etchmap.h"
+#include "etchexcp.h"
+unsigned id_name_get_hashkey(objmask*);
+
+
+/**
+ * new_id_name() 
+ * constructor accepting name. id is generated from a hash of the name.
+ * allocates, initializes and returns an etch_id_name*. the specified
+ * name is cloned, thus the etch_id_name owns all its memory (note that
+ * this may not be the case for derived classes such as etch_type).
+ */
+etch_id_name* new_id_name(const wchar_t* name) 
+{
+    etch_id_name* idn = NULL;
+    wchar_t* namecopy = NULL;
+    size_t   bytelen  = 0;
+    if (NULL == name) return NULL;
+
+    idn = (etch_id_name*) new_object
+        (sizeof(etch_id_name), ETCHTYPEB_ID_NAME, CLASSID_ID_NAME);
+
+    idn->destroy = destroy_id_name;
+    idn->clone   = clone_id_name;
+
+    bytelen  = ( wcslen(name) + 1 ) * sizeof(wchar_t);
+    namecopy = etch_malloc(bytelen, ETCHTYPEB_BYTES); 
+    /* wcscpy_s(namecopy, bytelen, name) causes a release build to hang at
+     * shutdown when the string is length 4 or more. let's not use wcscpy_s 
+     * until we can determine the cause. */
+    #pragma warning(disable:4996) /* disable nonsecure function warning */
+    wcscpy(namecopy, name);
+
+    /* carrying both name versions is first step in the 8-bit conversion */
+    /* etch_unicode_to_utf8() returns us an etch_malloc'ed buffer which we own */
+    etch_unicode_to_utf8 (&idn->aname, (wchar_t*) name);
+    
+    idn->name = namecopy; /* use wide name to compute hash etc. for now */
+    idn->id = compute_id_name_id_from_widename((wchar_t*)name); 
+    idn->namebytelen = bytelen;
+    idn->get_hashkey = id_name_get_hashkey;
+    idn->get_hashkey((objmask*)idn);
+
+    return idn;
+}
+
+
+/**
+ * new_id_name_from_8bitname() 
+ * constructor accepting narrow character name. 
+ * name is maintained internally as unicode.  
+ * see comments at new_id_name()
+ * note that this ctor will not be needed after 8-bit conversion.
+ */
+etch_id_name* new_id_name_from_8bitname(char* name) 
+{
+    etch_id_name* idn = NULL;
+
+    if (name)     /* eschew etch_malloc since freed immediately */
+    {   wchar_t* ubuf = malloc((strlen(name) + 1) * sizeof(wchar_t));
+
+        if (0 == etch_utf8_to_unicode(&ubuf, name))
+            idn = new_id_name(ubuf);
+
+        free(ubuf);
+    }
+    
+    return idn;
+}
+
+
+/**
+ * clone_id_name() 
+ * copy constructor 
+ */
+etch_id_name* clone_id_name (const etch_id_name* thatidn) 
+{
+    etch_id_name* newidn = thatidn? new_id_name (thatidn->name): NULL;
+    if (newidn)
+    {   newidn->obj_type = thatidn->obj_type;
+        newidn->class_id = thatidn->class_id;
+    }
+    return newidn;
+}
+
+
+/**
+ * destroy_id_name()
+ * destructor for an etch_id_name object.
+ * deallocates all memory allocated for the object and its contents.
+ */
+int destroy_id_name(etch_id_name* thisp)
+{
+    if (!thisp || thisp->refcount > 0 && --thisp->refcount > 0)  
+        return -1;  
+    
+    if (!is_etchobj_static_content(thisp))  
+    {
+        if (thisp->impl)
+            thisp->impl->destroy(thisp->impl); 
+
+        etch_free (thisp->name); 
+        etch_free( thisp->aname);
+    }
+
+    if (!is_etchobj_static_shell(thisp))    
+        etch_free(thisp);
+ 
+    return 0;
+}
+
+
+/**
+ * compute_id_name_id() 
+ * this algorithm and its result must be identical to that of the java binding.  
+ */
+int compute_id_name_id (const char* name)
+{
+    char c, *p = (char*) name;
+    int  h6, i = 0, hash = 5381;
+    const int numchars = (const int) strlen(name);
+
+    for (; i < numchars; i++, p++)
+    {
+    	c  = *p;
+    	h6 = hash << 6;
+    	hash = (h6 << 10) + h6 - hash + c;
+    }
+
+    return hash;
+}
+
+
+/**
+ * compute_id_name_id_from_widename() 
+ * see comments at compute_id_name_id() 
+ */
+int compute_id_name_id_from_widename (const wchar_t* name)
+{
+    char *cbuf = NULL;  
+    int   idname_id = 0;   
+
+    /* etch_unicode_to_utf8() returns us an etch_malloc'ed buffer which we own */
+    const int result = etch_unicode_to_utf8(&cbuf, (wchar_t*) name);
+    if (-1 == result) return -1;
+     
+    idname_id = compute_id_name_id(cbuf);
+ 
+    etch_free(cbuf);
+    return idname_id;
+}
+
+
+/**
+ * is_equal_id_names()
+ */
+int is_equal_id_names (etch_id_name* thisx, etch_id_name* thatx)
+{
+    const int result = thisx && thatx 
+      && (thisx->class_id == thatx->class_id) && (thisx->id == thatx->id);  
+    return result; 
+}
+
+
+/**
+ * is_good_id_name()
+ * verify that the id_name is complete
+ */
+int is_good_id_name (etch_id_name* p)
+{
+    const int result = p && p->name && p->id && p->namebytelen && p->hashkey;
+    return result; 
+}
+
+
+/**
+ * id_name_get_hashkey
+ * hashkey computation for an id_name object.
+ * hash key is computed using the name string as hash source.
+ */
+unsigned id_name_get_hashkey (objmask* idn)
+{
+    etch_id_name* thisx = (etch_id_name*) idn;
+
+    /* continue to use wide name to compute hash until it is eliminated */
+    idn->hashkey = etch_get_wchar_hashkey(thisx->name);
+
+    return idn->hashkey;
+}
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_message.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_message.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_message.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_message.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,381 @@
+/* $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_message.c
+ * message object
+ */
+
+#include "etch_message.h"
+#include "etch_global.h"
+#include "etchlog.h"
+char* ETCHMESS = "MESS";
+
+etch_message* new_message_init(etch_type*, const int);
+
+
+/**
+ * new_message()  
+ * constructor for etch_message
+ * the value factory is a reference, the type is a copy to be passed through
+ * to the underlying struct, which will then own the type memory.
+ */
+etch_message* new_message (etch_type* type, const int size, etch_value_factory* vf) 
+{
+    etch_message* newmsg = NULL;
+    if (!type || !vf) return NULL;
+
+    newmsg = new_message_init(type, size);
+    if (newmsg == NULL) return NULL;
+
+    newmsg->vf = vf; 
+    etchlog(ETCHMESS, ETCHLOG_XDEBUG, "creating message %x\n", newmsg);
+    return newmsg;
+}
+
+
+/**
+ * new_message_init() 
+ * common initialization on etch_message construction.
+ */
+etch_message* new_message_init(etch_type* type, const int initialsize)
+{
+    etch_message* newmsg = NULL;
+    if (NULL == type) return NULL;
+
+    newmsg = (etch_message*) new_object(sizeof(etch_message), 
+        ETCHTYPEB_MESSAGE, CLASSID_ETCHMESSAGE);
+    
+    newmsg->destroy = destroy_message;
+    newmsg->sv = new_structvalue(type, initialsize);
+
+    return newmsg;
+}
+
+
+/**
+ * destroy_message()
+ * destructor for etch_message
+ */ 
+int destroy_message (etch_message* msg) 
+{
+    int result = 0;
+    if (msg->refcount > 0 && --msg->refcount > 0) return -1;  
+
+    if (!is_etchobj_static_content(msg))
+    {    etchlog(ETCHMESS, ETCHLOG_XDEBUG, "destroying message %x\n", msg);
+         result = destroy_structvalue(msg->sv);
+    }
+
+    destroy_objectex((objmask*)msg);
+    return result;    
+}
+
+
+/**
+ * message_remove()
+ * removes an element from the message struct, returning the element.
+ * if the element is found, its key is destroyed, and the object is returned.
+ * caller owns returned object.
+ */ 
+objmask* message_remove(etch_message* msg, etch_field* key)
+{
+    return structvalue_remove(msg->sv, key);
+}
+
+
+/**
+ * message_put()
+ * insert key/value pair
+ *
+ * @param key an etch_field whose destructor will be invoked when the struct is
+ * destroyed. 
+ *
+ * @param value a *disposable* object which is the value of the key/val pair.
+ * if passed as null, specified key is removed from the message, per java binding.
+ * otherwise this object's destructor will be invoked when its struct is destroyed.
+ *
+ * @return 0 or -1. 
+ * on failure, destructors are invoked here on both key and value.
+ *
+ * remarks: to simplify caller logic under normal circumstances, caller
+ * relinquishes ownership of parameters (other than this of course), regardless
+ * of outcome. should caller wish to retain ownership on failure, the parameter
+ * object could be marked such that the destructor invoked here becomes benign.
+ */ 
+int message_put (etch_message* msg, etch_field* key, objmask* value) 
+{ 
+    #if(0)
+    if (NULL == key || NULL == msg->sv) 
+        etch_throw((objmask*)msg, EXCPTYPE_ILLEGALARG, NULL, 0);
+    else
+    if (0 > structvalue_put(msg->sv, key, value))     
+        etch_throw((objmask*)msg, EXCPTYPE_IO, NULL, 0);
+    return msg;
+    #endif
+
+    /* on success, struct owns key and value */
+    if (0 == structvalue_put(msg->sv, key, value))
+        return 0;
+
+    ETCHOBJ_DESTROY(value);
+    destroy_field(key); /* note we are often passed protected vf keys */
+    return -1; 
+}
+
+
+/**
+ * message_putc()
+ * insert key/value pair and clear value reference
+ *
+ * @param key an etch_field whose destructor will be invoked when the struct is
+ * destroyed. 
+ *
+ * @param value an indirect reference to a *disposable* object which is the value 
+ * of the key/val pair.
+ * caller's reference is nulled out once this object is relinquished; thus caller
+ * can safely test for null and then destroy the object.
+ *
+ * @return 0 or -1. 
+ * on failure, destructors are invoked here on both key and value.
+ *
+ * remarks: to simplify caller logic under normal circumstances, caller
+ * relinquishes ownership of parameters (other than this of course), regardless
+ * of outcome. should caller wish to retain ownership on failure, the parameter
+ * object could be marked such that the destructor invoked here becomes benign.
+ */ 
+int message_putc (etch_message* msg, etch_field* key, void** valref) 
+{ 
+    objmask* value = NULL;
+
+    if (valref)
+    {   value = (objmask*) *valref;
+        *valref = NULL;  /* clear caller's reference as we now own value */
+    }
+    
+    if (value) /* on success, struct owns key and value */
+        if (0 == structvalue_put (msg->sv, key, value))
+            return 0;
+
+    /* a struct put was not successful so destroy parameter objects */
+    ETCHOBJ_DESTROY(value);
+    destroy_field(key);  /* note we are often passed protected vf keys */
+    return -1; 
+}
+
+
+/**
+ * message_get()
+ * fetch value for key.
+ * @return a non-disposable reference to the value, not a copy, or null.
+ */
+objmask* message_get (etch_message* msg, etch_field* key)
+{
+    objmask* retobj = NULL;
+
+    if (msg && key && msg->sv)
+        retobj = structvalue_get(msg->sv, key); 
+
+    #if(0)
+    if (NULL == msg || NULL == key || NULL == msg->sv) 
+        return throw_from(EXCPTYPE_ILLEGALARG, ETCHTYPEB_UNDEFINED, 0, 0); 
+    retobj = structvalue_get(msg->sv, key); 
+    #endif
+     
+    return retobj; 
+}
+
+
+/**
+ * message_type()
+ * return etch type of specified message
+ */
+etch_type* message_type(etch_message* msg)
+{
+    return msg && msg->sv? msg->sv->struct_type: NULL;
+}
+
+
+/**
+ * message_aname()
+ * return name of specified message in 8-bit encoding.
+ * @return a reference to the message name, caller does not own it.
+ */
+char* message_aname (etch_message* msg)
+{
+    etch_type* msgtype = message_type(msg);
+    char*  msgname = msgtype && msgtype->aname? msgtype->aname: etch_emptystra;
+    return msgname;
+}
+
+
+/**
+ * message_reply()
+ * creates a message which is a reply to the current message.
+ * the current message's value factory is copied to the new message. 
+ * message id of the current message (if any) is copied into the 
+ * in-reply-to field of the new message.
+ * @param newtype the type of the reply. caller retains ownership.
+ * @return a reply message, which will contain exception if error.
+ */ 
+etch_message* message_reply (etch_message* msg, etch_type* newtype)  
+{
+    int result = -1;
+    etch_int64*   msgid  = NULL;
+    etch_message* newmsg = NULL;
+
+    if (NULL == msg) return NULL;
+
+    if (NULL == newtype) /* use message type's result type */
+        newtype = etchtype_get_result_type (msg->sv->struct_type);
+
+    if (NULL == newtype) return NULL;
+
+    /* construct message. caller retains ownership of type */
+    newmsg = new_message (newtype, 0, msg->vf);  
+
+    msgid  = message_get_id (msg); /* get back a ref to ID or null */
+
+    if (msgid)  
+        result = message_set_in_reply_to (newmsg, msgid->clone(msgid));
+    
+    if (0 != result)
+    {
+        ETCHOBJ_DESTROY(newmsg);
+        newmsg = NULL;
+    }     
+
+    return newmsg;
+}
+
+
+/**
+ * message_set_id()
+ * sets the message-id field of this message.
+ * @param id a *disposable* long object wrapping the connection specific 
+ * unique identifier of this message, or NULL if the message has not yet
+ * been sent. NOTE that the send process overwrites any value which might 
+ * otherwise be set here.
+ */ 
+int message_set_id(etch_message* msg, etch_int64* id)
+{
+    int  result = 0;
+    if (!id) return -1;       
+
+    /* id object ownership is relinquished here even if the call fails */
+    result = msg->vf->vtab->set_message_id(msg->vf, msg, id);
+    return result;
+}
+
+
+/**
+ * message_get_id()
+ * @return a non-disposable reference to the connection specific unique  
+ * identifier of this message, or null if there was no such identifier. 
+ */ 
+etch_int64* message_get_id(etch_message* msg)
+{
+    etch_int64* id = msg->vf->vtab->get_message_id(msg->vf, msg);
+    return id;
+}
+
+
+/**
+ * message_get_in_reply_to()
+ * @return a non-disposable reference to the message-id of the message that 
+ * this message is a response to, or null if this is an original message 
+ * or if the original message did not have a message-id. 
+ * caller does not own the returned object.
+ */ 
+etch_int64* message_get_in_reply_to(etch_message* msg)
+{
+    /* vf returns to us a reference to its value */
+    etch_int64* id = msg->vf->vtab->get_in_reply_to(msg->vf, msg);
+    return id;
+}
+
+
+/**
+ * message_set_in_reply_to()
+ * sets the in-reply-to field of this message.
+ * @param msgid a *disposable* long object wrapping the message-id of the 
+ * message that this message is a response to. note that caller must clone 
+ * or otherwise supply a disposable object as this parameter.  
+ */ 
+int message_set_in_reply_to(etch_message* msg, etch_int64* msgid)
+{
+    int result = 0;
+    if (!msgid) return -1;       
+
+    /* msgid ownership is relinquished here even if the call fails */
+    result = msg->vf->vtab->set_in_reply_to(msg->vf, msg, msgid);
+    return result;
+}
+
+
+/**
+ * message_size()
+ */ 
+
+int message_size (etch_message* msg) 
+{
+    return msg? structvalue_count(msg->sv): 0;
+}
+
+
+/* - - - - - - - - - - -
+ * etch_unwanted_message
+ * - - - - - - - - - - -
+ */
+  
+/**
+ * destroy_unwanted_message()
+ * etch_unwanted_message destructor
+ */
+int destroy_unwanted_message(etch_unwanted_message* msg)
+{
+   if (msg->refcount > 0 && --msg->refcount > 0) return -1;  
+
+    if (!is_etchobj_static_content(msg))
+    {   
+        if (msg->message)
+            msg->message->destroy(msg->message);
+    }
+
+   return destroy_objectex((objmask*) msg);
+}
+
+
+/**
+ * new_unwanted_message()
+ * etch_unwanted_message constructor
+ * @param whofrom caller retains
+ * @param msg caller relinquishes
+ */
+etch_unwanted_message* new_unwanted_message(etch_who* whofrom, etch_message* msg)
+{
+   etch_unwanted_message* newmsg = (etch_unwanted_message*) new_object
+     (sizeof(etch_unwanted_message), ETCHTYPEB_EVENT, CLASSID_EVENT_UNWANTMSG);
+
+    newmsg->destroy = destroy_unwanted_message;
+    newmsg->clone   = clone_null;
+
+    newmsg->message = msg;
+    newmsg->whofrom = whofrom;
+    return newmsg;
+}

Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_structval.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_structval.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_structval.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_structval.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,241 @@
+/* $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_structval.c -- etch_structvalue implementation.
+ */
+
+#include "etch_structval.h"
+#include "etch_validator.h"
+#include "etch_encoding.h"
+#include "etch_global.h"
+#include "etchexcp.h"
+#include "etchmap.h"
+#include "etchlog.h"
+char* ETCHSVAL = "SVAL";
+
+etch_structvalue* new_structvalue_init();
+int structvalue_clear_handler (etch_field* key, objmask* value);
+
+
+/**
+ * new_structvalue()  
+ * primary constructor for etch_structvalue. 
+ * @param etch_type object, caller retains ownership of the type as usual
+ */
+etch_structvalue* new_structvalue(etch_type* type, const int initialsize)
+{
+    etch_structvalue* newobj = new_structvalue_init(initialsize);
+
+    newobj->struct_type = type;
+
+    return newobj;
+}
+
+
+/**
+ * new_structvalue_init() (private)
+ * common initialization on etch_structvalue construction.
+ */
+etch_structvalue* new_structvalue_init(const int initialsize)
+{
+    etch_structvalue* newobj = etch_malloc(sizeof(etch_structvalue), ETCHTYPEB_STRUCTVAL);
+    memset(newobj, 0, sizeof(etch_structvalue));
+    newobj->obj_type = ETCHTYPEB_STRUCTVAL;
+    newobj->class_id = CLASSID_STRUCTVALUE; /* for now anyway */
+
+    newobj->destroy = destroy_structvalue;
+    newobj->clone   = clone_null;
+
+    newobj->items = new_structvalue_hashtable(initialsize);
+    /* mark map such that it knows its keys and values are etch objects */
+    newobj->items->content_type = ETCHHASHTABLE_CONTENT_OBJECT_OBJECT;
+
+    return newobj;
+}
+
+
+/**
+ * destroy_structvalue()
+ * destructor for an etch_structvalue object
+ *
+ * a structvalue owns all its memory *except* its type object, which is global  
+ * to the vf. this means that (a) the etch_type supplied on construction must be   
+ * a reference to a type owned by the service vf (or the unit test); and (b) all 
+ * struct keys must be etch_field* allocated on the heap and not referenced again 
+ * outside of that structvalue scope; and (c) all struct values must be etch object
+ * references allocated on the heap and not referenced again outside of the 
+ * structvalue scope.
+ */
+int destroy_structvalue(etch_structvalue* thisp) 
+{
+    if (NULL == thisp) return 0;
+    if (thisp->refcount > 0 && --thisp->refcount > 0) return -1;  
+        
+    if (!is_etchobj_static_content(thisp))
+        ETCHOBJ_DESTROY(thisp->items);
+
+    /* see comments above as to why we don't destroy type */
+
+    destroy_objectex((objmask*)thisp);   
+    return 0;
+}
+
+
+/* 
+ * structvalue_clear_handler()
+ * this callback is set to handle freeing of key and value memory during a clear()
+ * of the structvalue map. structs own all their memory, so if there is a problem
+ * here, it should be resolved at the source, not by modifying this code.
+ */
+int structvalue_clear_handler (etch_field* key, objmask* value)  
+{
+    destroy_field(key);
+    value->destroy(value);
+    return TRUE; 
+}
+
+
+/*  
+ * new_structvalue_hashtable
+ * create the backing store for a struct value
+ */
+etch_hashtable* new_structvalue_hashtable(const int initialsize) 
+{    
+    etch_hashtable* ht = new_hashtable(initialsize);  
+    if (ht == NULL) return NULL;
+    ht->content_type       = ETCH_STRUCT_DEFAULT_CONTENT_TYPE;
+    ht->is_tracked_memory  = ETCH_STRUCT_DEFAULT_TRACKED_MEM;
+    ht->is_readonly_keys   = ETCH_STRUCT_DEFAULT_READONLY_KEY;
+    ht->is_readonly_values = ETCH_STRUCT_DEFAULT_READONLY_VAL;
+    ht->freehook = structvalue_clear_handler;
+    return ht;
+}
+
+
+/**
+ * structvalue_put()
+ * inserts (or removes) specified key/value pair to/from struct store.
+ * @param key an etch_field whose destructor will be invoked when the struct is
+ * destroyed. presumably this etch_field is disposable; if not, the object must
+ * be marked as immutable using set_etchobj_static_all.
+ * @param value a *disposable* object which is the value of the key/val pair.
+ * this object's destructor will be invoked when the struct is destroyed.
+ * presumably this object and its content are disposable; if not, the object must
+ * be marked accordingly using set_etchobj_static_all or set_etchobj_static_content.
+ * returns 0 or -1.
+ */
+int structvalue_put (etch_structvalue* thisp, etch_field* key, objmask* value) 
+{
+    etch_hashtable* map = thisp->items;
+    if (NULL == key) return -1;
+
+    if (NULL == value)  /* per contract, no value implies removal desired */
+        return map->vtab->removeh (map->realtable, key->hashkey, key, 0);
+  
+    if (config.is_validate_on_write)
+    {   
+        etch_type* thistype = thisp->struct_type;
+        char *errmsg = NULL;
+
+        etch_validator* vtor = (etch_validator*) 
+            etchtype_get_validator_by_name (thistype, key->name);
+
+        if (NULL == vtor)
+            errmsg = "validator missing";
+        else
+        if (0 != vtor->validate (vtor, (etch_object*) value))
+            errmsg = "validation failed";
+
+        if (errmsg)
+        {   etchlog(ETCHSVAL, ETCHLOG_ERROR, "%s for type '%s' field '%s'\n", 
+                    errmsg, thistype->aname, key->aname);
+            return -1;
+        }
+    } 
+
+    return map->vtab->inserth (map->realtable, key, value, map, 0);    
+}
+
+
+/**
+ * structvalue_get()
+ * access an element from the struct.
+ * returns a reference not a copy.
+ */
+objmask* structvalue_get (etch_structvalue* thisp, etch_field* key) 
+{
+    int  result = 0;
+    etch_hashitem   hashbucket;
+    etch_hashitem*  thisitem = &hashbucket; 
+    etch_hashtable* map = thisp? thisp->items: NULL;
+    if (NULL == map) return NULL;
+
+    result = map->vtab->findh(map->realtable, key->hashkey, map, &thisitem);
+    
+    return result == 0? thisitem->value: NULL;
+}
+
+
+/**
+ * structvalue_remove
+ * removes an element from the struct, returning the element.
+ * if the element is found, its key is destroyed, and the object is returned.
+ * caller owns returned object.
+ */
+objmask* structvalue_remove(etch_structvalue* thisp, etch_field* key) 
+{
+    int  result = 0;
+    etch_hashitem   hashbucket;
+    etch_hashitem*  thisitem = &hashbucket; 
+    etch_hashtable* map = thisp? thisp->items: NULL;
+    memset(thisitem,0,sizeof(etch_hashitem));
+    if (NULL == map) return NULL;
+
+    /* remove specified item from hashtable without destroying content */
+    result = map->vtab->removeh(map->realtable, key->hashkey, map, &thisitem);
+    if (-1 == result) return NULL;
+
+    /* free entry key */
+    if (thisitem->key) 
+        if  (etchmap_is_object_key(map))
+            ((objmask*)thisitem->key)->destroy(thisitem->key);
+        else etch_free(thisitem->key);
+    
+    return (objmask*) thisitem->value;
+}
+
+
+/**
+ * structvalue_is_type()
+ * indicates if type of this struct is the same as the specified type
+ */
+int structvalue_is_type(etch_structvalue* thisp, etch_type* type)
+{
+    return is_equal_types(thisp->struct_type, type);
+}
+
+
+/**
+ * structvalue_count()
+ * returns number of pairs in the struct
+ */
+int structvalue_count(etch_structvalue* sv)
+{
+    return etchmap_count(sv->items);
+}

Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,643 @@
+/* $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.c -- tagged data implementation.
+ */
+
+#include "etch_tagdata.h"
+#include "etch_global.h"
+#include "etch_type.h"
+#include "etch_arrayval.h"
+
+
+/* the only instance data in the java version is the value factory 
+ * for C, inheritors can implement that, in order that we don't need
+ * any instance data here and can just implement methods. 
+ */
+
+/*
+ * etchtagdata_get_number()
+ * java.Lang.Number emulation support.
+ * given an anonymous wrapped primitive, return its value represented as
+ * a 64-bit integer.
+ */
+int etchtagdata_get_number(etch_object* valobj, 
+    const double fmin, const double fmax, int64* out)
+{
+    int64 longval = 0;
+    double dval;
+    if (!is_etch_primitive_number(valobj)) return -1; 
+
+    switch(valobj->class_id)
+    { 
+        case CLASSID_PRIMITIVE_INT32:
+             longval = ((etch_int32*)valobj)->value;
+             break; 
+
+        case CLASSID_PRIMITIVE_INT64:
+             longval = ((etch_int64*)valobj)->value;
+             break;
+
+        case CLASSID_PRIMITIVE_BYTE:
+        case CLASSID_PRIMITIVE_BOOL: 
+        case CLASSID_PRIMITIVE_INT8: 
+             longval = ((etch_byte*)valobj)->value;
+             break;
+
+        case CLASSID_PRIMITIVE_INT16:
+             longval = ((etch_int16*)valobj)->value;
+             break;
+         
+        case CLASSID_PRIMITIVE_DOUBLE: 
+        case CLASSID_PRIMITIVE_FLOAT:  
+        {   
+            switch(valobj->class_id)
+            { case CLASSID_PRIMITIVE_DOUBLE:
+                   dval = ((etch_double*)valobj)->value;
+                   break;
+              case CLASSID_PRIMITIVE_FLOAT:
+                   dval = (double) ((etch_float*)valobj)->value;
+                   break;
+            }
+
+            /* round ieee value if necessary */
+            if (dval >= 0.0 && dval <= fmax) 
+                dval += 0.5;
+            else
+            if (dval  < 0.0 && dval >= fmin)
+                dval -= 0.5;
+
+            longval = (int64) dval;   
+            break;
+        }
+    }
+
+    *out = longval;
+    return 0;
+}
+
+
+/*
+ * etchtagdata_get_fnumber()
+ * java.Lang.Number emulation support.
+ * given an anonymous wrapped primitive, return its value represented as
+ * an IEEE number of 64 bits.
+ */
+int etchtagdata_get_double_number(etch_object* valobj,  
+    const double fmin, const double fmax, double* outd)
+{
+    float fval = 0.0; double dval = 0.0; int64 longval = 0;
+
+    if (-1 == etchtagdata_get_number(valobj, fmin, fmax, &longval))
+        return -1;
+  
+    switch(valobj->class_id)
+    { 
+        case CLASSID_PRIMITIVE_DOUBLE: 
+           dval = ((etch_double*)valobj)->value; 
+           break;
+
+        case CLASSID_PRIMITIVE_FLOAT:  
+            fval = ((etch_float*)valobj)->value;
+            dval = (double) fval;
+            break;
+
+        default:
+            dval = (double) longval;
+    }
+
+    *outd = dval;
+    return 0;
+}
+
+
+/*
+ * etchtagdata_get_float_number()
+ * java.Lang.Number emulation support.
+ * given an anonymous wrapped primitive, return its value represented as
+ * an IEEE number of 32 bits.
+ */
+int etchtagdata_get_float_number(etch_object* valobj,
+    const double fmin, const double fmax, float* outf)
+{
+    float fval = 0.0; double dval = 0.0; int64 longval = 0;
+
+    if (-1 == etchtagdata_get_number(valobj, fmin, fmax, &longval))
+        return -1;
+   
+    switch(valobj->class_id)
+    { 
+        case CLASSID_PRIMITIVE_DOUBLE: 
+           dval = ((etch_double*)valobj)->value; 
+           fval = (float) dval;
+           break;
+
+        case CLASSID_PRIMITIVE_FLOAT:  
+            fval = ((etch_float*)valobj)->value;
+            break;
+
+        default:
+            fval = (float) longval;
+    }
+
+    *outf = fval;
+    return 0;
+}
+
+
+/*
+ * etchtagdata_byte_value()
+ * mimic java.Lang.Number.byteValue()
+ */
+int etchtagdata_byte_value(etch_object* valobj, byte* out)
+{
+    const static double ETCHTYPE_MAX_BYTEF = ETCHTYPE_MAX_BYTE + 0.4999;
+    const static double ETCHTYPE_MIN_BYTEF = ETCHTYPE_MIN_BYTE - 0.4999;
+    int64 longval = 0;
+
+    const int result = etchtagdata_get_number(valobj, 
+          ETCHTYPE_MIN_BYTEF, ETCHTYPE_MAX_BYTEF, &longval);
+
+    if (0 == result && out) 
+       (*out) = (byte) longval;  /* truncate and return value */
+ 
+    return result;  
+}
+
+
+/*
+ * etchtagdata_bool_value()
+ * if there was a java.Lang.Number.booleanValue(), this would mimic it
+ */
+int etchtagdata_bool_value(etch_object* valobj, boolean* out)
+{
+    const static double ETCHTYPE_MAX_BOOLF =  1.4999;
+    const static double ETCHTYPE_MIN_BOOLF = -0.4999;
+    int64 longval = 0;
+
+    const int result = etchtagdata_get_number(valobj, 
+          ETCHTYPE_MIN_BOOLF, ETCHTYPE_MAX_BOOLF, &longval);
+
+    if (0 == result && out) 
+    {   boolean bool_out = (boolean) longval; /* truncate value */
+        if (bool_out > 1) bool_out = 1;
+        else if (bool_out < 0) bool_out = 0;
+        (*out) = bool_out;  /* return value */
+    } 
+ 
+    return result;  
+}
+
+
+/*
+ * etchtagdata_int16_value()
+ * mimic java.Lang.Number.shortValue()
+ */
+int etchtagdata_int16_value(etch_object* valobj, short* out)
+{
+    const static double ETCHTYPE_MAX_INT16F = ETCHTYPE_MAX_INT16 + 0.4999;
+    const static double ETCHTYPE_MIN_INT16F = ETCHTYPE_MIN_INT16 - 0.4999;
+    int64 longval = 0;
+
+    const int result = etchtagdata_get_number(valobj, 
+          ETCHTYPE_MIN_INT16F, ETCHTYPE_MAX_INT16F, &longval);
+
+    if (0 == result && out) 
+       (*out) = (short) longval;  /* truncate and return value */
+ 
+    return result;
+}
+
+
+/*
+ * etchtagdata_int32_value()
+ * mimic java.Lang.Number.intValue()
+ */
+int etchtagdata_int32_value(etch_object* valobj, int* out)
+{
+    const static double ETCHTYPE_MAX_INT32F = ETCHTYPE_MAX_INT32 + 0.4999;
+    const static double ETCHTYPE_MIN_INT32F = ETCHTYPE_MIN_INT32 - 0.4999;
+    int64 longval = 0;
+
+    const int result = etchtagdata_get_number(valobj, 
+          ETCHTYPE_MIN_INT32F, ETCHTYPE_MAX_INT32F, &longval);
+
+    if (0 == result && out) 
+       (*out) = (int) longval;  /* truncate and return value */
+ 
+    return result;
+}
+
+
+/*
+ * etchtagdata_int64_value()
+ * mimic java.Lang.Number.longValue()
+ */
+int etchtagdata_int64_value(etch_object* valobj, int64* out)
+{
+    const static double ETCHTYPE_MAX_INT64F = (double) ETCHTYPE_MAX_INT64;
+    const static double ETCHTYPE_MIN_INT64F = (double) ETCHTYPE_MIN_INT64;
+    int64 longval = 0;
+
+    const int result = etchtagdata_get_number(valobj, 
+          ETCHTYPE_MIN_INT64F, ETCHTYPE_MAX_INT64F, &longval);
+
+    if (0 == result && out) 
+       (*out) = longval; 
+ 
+    return result;
+}
+
+
+/*
+ * etchtagdata_float_value()
+ * mimic java.Lang.Number.floatValue()
+ */
+int etchtagdata_float_value(etch_object* valobj, float* out)
+{
+    const static double ETCHTYPE_MAX_FLOATF = ETCHTYPE_MAX_FLOAT + 0.4999;
+    const static double ETCHTYPE_MIN_FLOATF = ETCHTYPE_MIN_FLOAT - 0.4999;
+    float floatval = 0.0;
+
+    const int result = etchtagdata_get_float_number(valobj, 
+          ETCHTYPE_MIN_FLOATF, ETCHTYPE_MAX_FLOATF, &floatval);
+
+    if (0 == result && out) 
+       (*out) = floatval; 
+ 
+    return result;
+}
+
+
+/*
+ * etchtagdata_double_value()
+ * mimic java.Lang.Number.doubleValue()
+ */
+int etchtagdata_double_value(etch_object* valobj, double* out)
+{
+    double dval = 0.0;
+
+    const int result = etchtagdata_get_double_number(valobj, 
+          ETCHTYPE_MIN_DOUBLE, ETCHTYPE_MAX_DOUBLE, &dval);
+
+    if (0 == result && out) 
+       (*out) = dval; 
+ 
+    return result;
+}
+
+
+/*
+ * etchtagdata_adjust_tiny_int()
+ * if target value is one byte and value is in range of tiny int,
+ * adjust the type code accordingly, returning it in out parameter
+ */
+int etchtagdata_adjust_tiny_int(const signed char target_type, etch_object* valobj, signed char* out)
+{
+    signed char type_out = target_type, byteval = 0;
+    int result = 0;
+
+    if (target_type == ETCH_XTRNL_TYPECODE_BYTE)
+        if (0 == (result = etchtagdata_byte_value(valobj, &byteval)))
+            if (is_inrange_tiny(byteval))
+                type_out = byteval; 
+
+    if (out) (*out = type_out);
+    return result;
+}
+
+
+/*
+ * etchtagdata_validate_value()
+ * in java binding this is checkValue(object, validator);
+ * defers to validator to determine type code for the value.
+ * adjusts the type to tiny integer if applicable and possible. 
+ * returns the type code in the out parameter.
+ */
+int etchtagdata_validate_value(etch_object* valobj, etch_validator* vtor, signed char* out)
+{
+    signed char xtype = 0; int result = 0;
+
+    if (NULL == valobj)
+        xtype = ETCH_XTRNL_TYPECODE_NULL;
+    else
+    if (etchtagdata_is_eod(valobj))
+        xtype = ETCH_XTRNL_TYPECODE_NONE; 
+    else
+    if (0 == (result = vtor->check_value(vtor, valobj, &xtype)))      
+        result = etchtagdata_adjust_tiny_int(xtype, valobj, &xtype);
+
+    if (out) (*out = xtype);
+    return result;
+
+}
+
+
+/**
+ * etchtagdata_check_value()
+ * returns a type code for the specified value
+ * @param valobj an etch value object, caller retains ownership.
+ */
+signed char etchtagdata_check_value (etch_object* valobj)
+{
+    signed char xtype = 0;
+    const unsigned int obj_type = valobj? valobj->obj_type: 0;
+    const unsigned int class_id = valobj? valobj->class_id: 0;
+
+    if (NULL == valobj)
+        xtype = ETCH_XTRNL_TYPECODE_NULL;
+    else
+    if (etchtagdata_is_eod(valobj))
+        xtype = ETCH_XTRNL_TYPECODE_NONE; 
+    else
+    if (is_etch_primitive(valobj))
+    {
+        switch(class_id)
+        {
+           case CLASSID_PRIMITIVE_INT32:  
+                 xtype = etchtagdata_check_integer(((etch_int32*)valobj)->value);
+                 break;
+            case CLASSID_PRIMITIVE_INT16:  
+                 xtype = etchtagdata_check_short(((etch_int16*)valobj)->value);
+                 break;
+            case CLASSID_PRIMITIVE_INT64:  
+                 xtype = etchtagdata_check_long(((etch_int64*)valobj)->value);
+                 break;
+            case CLASSID_PRIMITIVE_BYTE: 
+            case CLASSID_PRIMITIVE_INT8:  
+                 xtype = etchtagdata_check_byte(((etch_byte*)valobj)->value);     
+                 break;
+            case CLASSID_PRIMITIVE_DOUBLE:
+                 xtype = ETCH_XTRNL_TYPECODE_DOUBLE; 
+                 break;      
+            case CLASSID_PRIMITIVE_FLOAT: 
+                 xtype = ETCH_XTRNL_TYPECODE_FLOAT;
+                 break;                 
+            case CLASSID_PRIMITIVE_BOOL:  
+                 xtype = ((etch_boolean*)valobj)->value?   
+                     ETCH_XTRNL_TYPECODE_BOOLEAN_TRUE:  
+                     ETCH_XTRNL_TYPECODE_BOOLEAN_FALSE;  
+                 break; 
+           case CLASSID_STRING:         
+                 xtype = ((etch_string*)valobj)->char_count == 0?
+                     ETCH_XTRNL_TYPECODE_EMPTY_STRING:
+                     ETCH_XTRNL_TYPECODE_STRING;     
+                 break;
+            default: 
+                 xtype = ETCH_XTRNL_TYPECODE_CUSTOM;   
+                 break;
+        }  /* switch(class_id) */
+    }    
+    else switch(obj_type)
+    { 
+        case ETCHTYPEB_STRUCTVAL:
+             xtype = ETCH_XTRNL_TYPECODE_CUSTOM;   
+             break;
+        case ETCHTYPEB_ARRAYVAL:
+             xtype = ((etch_arrayvalue*)valobj)->content_obj_type == ETCHTYPEB_BYTE?
+                 ETCH_XTRNL_TYPECODE_BYTES: ETCH_XTRNL_TYPECODE_ARRAY;  
+             break;
+        case ETCHTYPEB_NATIVEARRAY:
+             xtype = ((etch_nativearray*)valobj)->content_obj_type == ETCHTYPEB_BYTE?
+                 ETCH_XTRNL_TYPECODE_BYTES: ETCH_XTRNL_TYPECODE_ARRAY;   
+             break;
+        default: 
+             xtype = ETCH_XTRNL_TYPECODE_CUSTOM;   
+    }
+    
+    return xtype;
+}
+
+
+/*
+ * etchtagdata_get_native_typecode()
+ * returns the external type code corresponding to internal type.
+ * see etch_binary_tdi.c for implementation
+ */
+byte etchtagdata_get_native_typecode
+    (const unsigned short obj_type, const unsigned short class_id)
+{
+    return ETCH_XTRNL_TYPECODE_NONE;
+}
+
+
+/*
+ * etchtagdata_get_native_type()
+ * returns the internal type and class ids corresponding to external typecode.
+ * see etch_binary_tdi.c for implementation
+ */
+unsigned etchtagdata_get_native_type (const byte typecode) 
+{
+    return (CLASSID_NONE << 16) | ETCHTYPEB_NONE;
+}
+
+
+/*
+ * etchtagdata_get_custom_structtype()
+ * returns a struct type for the specified class
+ * see etch_binary_tdi for implementation
+ */
+etch_type* etchtagdata_get_custom_structtype (etch_object* thisx, 
+   const unsigned short obj_type, const unsigned short class_id)
+{
+    /* we will return a non-disposable (static) type */
+    etch_type* type = NULL; 
+    return type;    
+}
+
+
+/**
+ * etchtagdata_to_arrayvalue()
+ * create an etch arrayvalue object from a native array.
+ * the java version accepts an object, presumably an array, possibly of arrays,
+ * drills down to the base dimension to get the array content type, and creates
+ * an arrayvalue of the resultant type and dimension count. for the c version,  
+ * we'll assume here that native arrays are wrapped as etch_nativearray. 
+ * an array of arrays will therefore have content type etch_nativearray. 
+ */
+etch_arrayvalue* etchtagdata_to_arrayvalue (etch_object* thisx,
+    etch_nativearray* value, tagdata_get_native_type_code fp_get_native_typecode)
+{
+    unsigned char  external_typecode   = 0;
+    unsigned short array_content_type  = 0;
+    unsigned short array_content_class = 0;
+    etch_type*  custom_structtype = NULL;
+    etch_component_type_params params; 
+    etch_component_type_params* p = &params;
+
+    /* get type of the array's members */
+    int result = etch_nativearray_get_component_type((etch_object*) value, p);
+    if (-1 == result) return NULL;
+    array_content_type  = p->final_obj_type;
+    array_content_class = p->final_class_id;
+
+    external_typecode = fp_get_native_typecode /* function pointer passed in */
+       (array_content_type, array_content_class); 
+    
+    /* class arrayvalue makes a copy of this type so we don't worry about ownership
+     * of the type object returned by etchtagdata_get_custom_structtype(), the type
+     * presumably looked up in the class2type map by the vf 
+     */
+    if (ETCH_XTRNL_TYPECODE_CUSTOM == external_typecode)
+    {
+        custom_structtype = etchtagdata_get_custom_structtype(thisx,
+            array_content_type, array_content_class); 
+    }
+
+    return new_arrayvalue(external_typecode, custom_structtype, 
+        p->dimensions, 0, 0, FALSE, ETCHARRAYLIST_SYNCHRONIZED);
+}
+
+
+/**
+ * etchtagdata_from_arrayvalue()
+ * return an etch_nativearray representation of the specified etch_arrayvalue.
+ * note that an arrayvalue, if created from an etch_nativearray, has retained 
+ * the source nativearray as an instance member. is_force indicates if caller
+ * wants to build the nativearray regardless of whether one currently exists.
+ */
+etch_nativearray* etchtagdata_from_arrayvalue(etch_arrayvalue* av, const int is_force)
+{
+    if (av->natarray && !is_force) return av->natarray;
+    return (-1 == arrayvalue_to_nativearray(av))? NULL: av->natarray;    
+}
+
+
+/**
+ * etchtagdata_alloc_arrayvalue()
+ * creates and returns an empty arrayvalue object. this method is here for
+ * for compatibility with the java binding, however it is superfluous.
+ * we can safely substitute the new_arrayvalue call below and lose this method. 
+ */
+etch_arrayvalue* etchtagdata_alloc_arrayvalue(const byte type_code, 
+    etch_type* custom_struct_type, const int dim, const int initsize)
+{
+     return new_arrayvalue(type_code, custom_struct_type, dim, 
+        initsize, initsize, FALSE, ETCHARRAYLIST_SYNCHRONIZED);
+}
+
+
+/*
+ * etchtagdata_check_byte()
+ */
+signed char etchtagdata_check_byte(const signed char val) 
+{
+    byte result = ETCH_XTRNL_TYPECODE_BYTE;
+    if (is_inrange_tiny(val))
+        result = val;   
+    return result;
+}  
+
+
+/*
+ * etchtagdata_check_short()
+ */
+signed char etchtagdata_check_short(const short val) 
+{
+    byte result = ETCH_XTRNL_TYPECODE_SHORT;
+    if (is_inrange_byte(val))
+        result = etchtagdata_check_byte((byte)val);
+    return result;
+}  
+
+
+/*
+ * etchtagdata_check_integer()
+ */
+signed char etchtagdata_check_integer(const int val) 
+{
+    byte result = ETCH_XTRNL_TYPECODE_INT;
+    if  (is_inrange_int16(val)) 
+         result = etchtagdata_check_short((short)val);
+    return result;
+}  
+
+
+/*
+ * etchtagdata_check_long()
+ */
+signed char etchtagdata_check_long(const int64 val) 
+{
+    byte result = ETCH_XTRNL_TYPECODE_LONG;
+    if  (is_inrange_int32(val)) 
+         result = etchtagdata_check_integer((int)val);
+    return result;
+} 
+
+
+/**
+ * etchtagdata_is_null()
+ * indicate whether this object represents a null value
+ */
+int etchtagdata_is_null(etch_object* obj)
+{
+    return obj == NULL || obj->is_null;
+} 
+
+
+/**
+ * etchtagdata_is_eod()
+ * indicate whether this object is the end of stream sentinel
+ */
+int etchtagdata_is_eod(etch_object* obj)
+{
+    return obj && obj->obj_type == ETCHTYPEB_EODMARK;
+}
+
+
+/**
+ * etchtagdata_new_nullobj()
+ * instantiate and return a logically null object
+ */
+objmask* etchtagdata_new_nullobj(const int is_static)
+{
+   objmask* obj = new_nullobj();
+   if (is_static) set_etchobj_static_all(obj);
+   return obj;
+}
+
+
+/**
+ * etchtagdata_new_eodmarker()
+ * instantiate and return an end of data marker object
+ */
+objmask* etchtagdata_new_eodmarker(const int is_static)
+{
+   objmask* obj = new_object(sizeof(objmask), ETCHTYPEB_EODMARK, CLASSID_NONE);
+   if (is_static) set_etchobj_static_all(obj);
+   return obj;
+}
+
+
+/**
+ * etchtagdata_new_emptystring()
+ * instantiate and return an empty string object
+ */
+etch_string* etchtagdata_new_emptystring(const int is_static)
+{
+   etch_string* obj = new_string(L"", ETCH_ENCODING_UTF16);
+   if (is_static) set_etchobj_static_all(obj);
+   return obj;
+}
+
+
+
+
+
+

Added: incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_inp.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_inp.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_inp.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/bindings/msg/etch_tagdata_inp.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,180 @@
+/* $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_inp.c -- tagged_data_input implementation.
+ */
+
+#include "etch_tagdata_inp.h"
+#include "etch_global.h"
+
+/**
+ * tdi_start_message()
+ */
+etch_message* tdi_start_message(tagged_data_input* tdi)
+{
+    return NULL;
+}
+
+
+etch_message* tdi_read_message(tagged_data_input* tdi, etch_flexbuffer* f)
+{
+    return NULL;
+}
+
+
+/**
+ * tdi_end_message()
+ */
+int tdi_end_message(tagged_data_input* tdi, etch_message* msg)
+{
+    return NULL;
+}
+
+
+/**
+ * tdi_start_struct()
+ */
+etch_structvalue* tdi_start_struct(tagged_data_input* tdi)
+{
+    return NULL;
+}
+
+
+/**
+ * tdi_read_struct()
+ */
+etch_structvalue* tdi_read_struct(tagged_data_input* tdi)
+{
+    return NULL;
+}
+
+
+/**
+ * tdi_end_struct()
+ * ends a struct currently being read
+ */
+int tdi_end_struct(tagged_data_input* tdi, etch_structvalue* sv)
+{
+    return 0;
+}
+
+
+/**
+ * tdi_start_array()
+ * starts reading an array from the stream 
+ */
+etch_arrayvalue* tdi_start_array(tagged_data_input* tdi)
+{
+    return NULL;
+}
+
+
+etch_arrayvalue* tdi_read_array(tagged_data_input* tdi, etch_validator* v)
+{
+    return NULL;
+}
+
+
+/**
+ * tdi_end_array()
+ */
+int tdi_end_array(tagged_data_input* tdi, etch_arrayvalue* x)
+{
+    return 0;
+}
+
+
+/**
+ * destroy_tagged_data_input()
+ */
+int destroy_tagged_data_input(tagged_data_input* tdi)
+{
+    if (tdi->refcount > 0 && --tdi->refcount > 0) return -1;  
+
+    if (!is_etchobj_static_content(tdi))
+        if (tdi->impl)
+            tdi->impl->destroy(tdi->impl);
+
+    destroy_objectex((objmask*)tdi);
+    return 0;
+}
+
+
+/**
+ * clone_tagged_data_input()
+ */
+tagged_data_input* clone_tagged_data_input(tagged_data_input* tdi)
+{
+    tagged_data_input* newtdi = (tagged_data_input*) clone_object((objmask*) tdi);
+
+    if (tdi->impl)
+        newtdi->impl = tdi->impl->clone(tdi->impl);
+
+    return newtdi;
+}
+
+
+/**
+ * new_tdi_vtable()
+ */
+i_tagged_data_input* new_tdi_vtable()
+{
+    i_tagged_data_input* vtab 
+        = new_vtable(NULL, sizeof(i_tagged_data_input), CLASSID_TDI_VTAB);
+
+    vtab->start_message = tdi_start_message;
+    vtab->read_message  = tdi_read_message;
+    vtab->end_message   = tdi_end_message;
+    vtab->start_struct  = tdi_start_struct;
+    vtab->read_struct   = tdi_read_struct;
+    vtab->end_struct    = tdi_end_struct;
+    vtab->start_array   = tdi_start_array;
+    vtab->read_array    = tdi_read_array;
+    vtab->end_array     = tdi_end_array;
+    return vtab;
+}
+
+
+/**
+ * new_tagged_data_input()
+ * tagged_data_input constructor 
+ */
+tagged_data_input* new_tagged_data_input(const short objtype, const short class_id)
+{
+    i_tagged_data_input* vtab = NULL;
+
+    tagged_data_input* tdi = (tagged_data_input*) new_object
+        (sizeof(tagged_data_input), ETCHTYPEB_TAGDATAINP, CLASSID_TAGDATAINP);
+
+    tdi->destroy = destroy_tagged_data_input;
+    tdi->clone   = clone_tagged_data_input;
+
+    vtab = cache_find(get_vtable_cachehkey(CLASSID_TDI_VTAB), 0);
+
+    if(!vtab)  
+    {    
+        vtab = new_tdi_vtable();
+        cache_insert(vtab->hashkey, vtab, FALSE);
+    } 
+ 
+    tdi->vtab = vtab;   
+    return tdi; 
+}
+
+