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 [17/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/common/etch_linklist.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/common/etch_linklist.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/common/etch_linklist.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/common/etch_linklist.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,305 @@
+/* $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_linklist.c -- implementation of linklist.
+ */
+
+#include <stdio.h>
+#include "etch_linklist.h"
+#include "etchmem.h"
+
+
+
+/**
+ * new_linkist()
+ * constructor for an etch_linklist.
+ * Creates the underlying list and returns a pointer to the list.
+ */
+etch_linklist* new_linklist()
+{
+    etch_linklist* list = etch_malloc(sizeof(etch_linklist), ETCHTYPEB_COLLECTION);
+    memset(list, 0, sizeof(etch_linklist));
+    return list;
+}
+
+
+/*
+ * linklist_clear() 
+ * remove all content from the arraylist, freeing bucket memory always, 
+ * and content memory if requested.  
+ */
+void linklist_clear(etch_linklist* list, const int is_free_content) 
+{
+    linklist_node *p = NULL, *nextp = NULL;
+    if (NULL == list) return;
+
+    for(p = list->head; p; p = nextp)
+    {   
+        if (is_free_content && p->content) 
+            etch_free(p->content);
+        nextp = p->next;
+        free(p);               
+    }
+
+    memset(list, 0, sizeof(etch_linklist));          
+}
+
+
+/**
+ * linklist_destroy()
+ * Destructor for an etch_linklist.
+ * Destroys the underlying list, the list shell, and the list content if requested.
+ */
+void linklist_destroy(etch_linklist* list, const int is_free_content) 
+{    
+    if (NULL == list) return;
+    linklist_clear(list, is_free_content);
+    etch_free(list);
+}
+
+
+/*
+ * linklist_add() 
+ * add a node to the end of the list, returning the new node's index
+ */
+int linklist_add(etch_linklist* list, void* content) 
+{
+    linklist_node* node = NULL;
+    if (NULL == list) return -1;
+
+    node = etch_malloc(sizeof(linklist_node), ETCHTYPEB_LINKLIST);
+    node->content = content;
+    
+    if (list->head == NULL) /* first entry? */
+        list->head = node;
+    else                   
+    {   assert(list->tail);    
+        list->tail->next = node;
+    }
+
+    list->tail = node;
+    return ++list->count;
+}
+
+
+/*
+ * linklist_insert() 
+ * add a node anywhere in the list, returning the new node's index,
+ * or -1 if a parameter was in error.
+ * this implementation cannot insert past the current end of list,
+ * in other words to insert at index n, there must be at least n
+ * entries currently in the list.
+ */
+int linklist_insert(etch_linklist* list, const unsigned int i, void* content)
+{
+    unsigned count = 0;
+    linklist_node* newnode = NULL, *p = NULL, *priorp = NULL;
+    if ((NULL == list) || (i > list->count) || (i < 0)) return -1;
+
+    newnode = etch_malloc(sizeof(linklist_node), ETCHTYPEB_LINKLIST);
+    newnode->content = content;
+    p = priorp = list->head;
+
+    if (list->head == NULL)
+        list->head = list->tail = newnode;
+    else
+    if (i == list->count)
+        list->tail->next = list->tail = newnode;
+    else
+    {   for(p = list->head; p, count < i; p = p->next, count++)
+            priorp = p;
+        
+        newnode->next = priorp->next;
+        priorp->next = newnode;
+    }
+
+    ++list->count;
+    return i;
+}
+
+
+/*
+ * linklist_moveto() 
+ * private method to move to an indicated index in the list.
+ * returns the index moved to, or -1 if a parameter was in error.
+ * returns also in outp, a pointer to the node at the requested position.
+ */
+int linklist_moveto(etch_linklist* list, const unsigned startat, const linklist_node** outp)
+{
+    unsigned count = 0;
+    linklist_node* p = NULL;
+    if ((NULL == list) || (startat > list->count) || (startat < 0)) return -1;
+  
+    for(p = list->head; p, count < startat; p = p->next, count++);
+    *outp = p;
+    return 0;
+}
+
+
+/*
+ * linklist_containsp() 
+ * return 1 or 0 indicating if the list contains the supplied content pointer,
+ * or -1 if a parameter was in error.
+ */
+int linklist_containsp(etch_linklist* list, void* content, const unsigned startat)
+{
+    struct linklist_node *p = NULL;
+
+    if (-1 == linklist_moveto(list, startat, &p)) return -1;
+
+    for(; p; p = p->next) 
+        if (p->content == content) 
+            return TRUE; 
+     
+    return FALSE;
+}
+
+
+/*
+ * linklist_indexofp() 
+ * if the list contains the supplied content pointer, return its index;
+ * return -1 if not found or if a parameter was in error.
+ */
+int linklist_indexofp(etch_linklist* list, void* content, const unsigned startat)
+{
+    struct linklist_node *p = NULL;
+    int count = startat, foundat = -1;
+
+    if (-1 == linklist_moveto(list, startat, &p)) return -1;
+
+    for(; p; p = p->next) 
+    {    
+        if (p->content == content) 
+        {   foundat = count;
+            break;
+        }        
+        else count++;
+    }
+     
+    return foundat;
+}
+
+
+/*
+ * linklist_contains() 
+ * return 1 or 0 indicating if the list contains the supplied content 
+ * or -1 if a parameter was in error.
+ * caller must supply a comparator function of signature int f(void* this, void* that), 
+ * which returns -1 if less, 0 if equal, 1 if greater. 
+ */
+int linklist_contains(etch_linklist* list, void* content, const unsigned startat, etch_comparator compare)
+{
+    struct linklist_node *p = NULL;
+    int result = 0;
+
+    if (!list || !compare) return -1;
+    if (-1 == linklist_moveto(list, startat, &p)) return -1;
+
+    for(; p; p = p->next) 
+    {
+        result = compare(content, p->content);
+        if (result == 0) return TRUE;
+    }
+     
+    return FALSE;
+}
+
+
+/*
+ * linklist_indexof() 
+ * if the list contains the supplied content pointer, return its index.
+ * return -1 if a parameter was in error.
+ * caller must supply a comparator function of signature: int (*f)(void* this, void* that); 
+ * which must return -1 if less, 0 if equal, 1 if greater. 
+ */
+int linklist_indexof(etch_linklist* list, void* content, const unsigned startat, etch_comparator compare)
+{
+    struct linklist_node *p = NULL;
+    int result = 0, count = startat, foundat = -1;
+
+    if (!list || !compare) return -1;
+    if (-1 == linklist_moveto(list, startat, &p)) return -1;
+
+    for(; p; p = p->next) 
+    {
+        result = compare(content, p->content);
+        if (result == 0) 
+        {   foundat = count;
+            break;
+        }        
+        else count++;
+    }
+     
+    return foundat;
+}
+
+
+/*
+ * linklist_get() 
+ * return entry at specified index position, or NULL if parameter error.
+ * if we find the lists are not generally short, we'll supply an indexed version of this list,
+ * and/or implement a resizable array of pointers which we block memcpy to insert and delete.
+ */
+linklist_node* linklist_get(etch_linklist* list, const unsigned i)
+{
+    unsigned count = 0;
+    struct linklist_node *p = NULL;
+    if ((NULL == list) || (i >= list->count) || (i < 0)) return NULL;
+
+    for(p = list->head; p; p = p->next, count++)
+        if (count == i) return p;
+
+    return NULL; /* can't arrive here */
+}
+
+
+/*
+ * linklist_remove() 
+ * remove entry at specified index position, free bucket memory; free content memory on request
+ * return -1 if a parameter was in error, or zero if OK.
+ */
+int linklist_remove(etch_linklist* list, const unsigned i, const int is_free_content)
+{
+    int priori = i - 1;
+    struct linklist_node *p = NULL, *priorp = NULL;
+    if (!list || (i >= list->count) || (i < 0)) return -1;
+           
+    /* move to node prior to requested node */
+    if (-1 == linklist_moveto(list, priori, &priorp)) 
+    {   
+        p = list->head;  /* asked to remove node[0] */
+        list->head = p->next;  
+        if (list->tail == p)
+            list->tail = NULL;
+    }
+    else
+    {   p = priorp->next;
+        priorp->next = p->next;
+        if (list->tail == p)
+            list->tail = priorp;
+    }
+
+    if (is_free_content && p->content)
+        etch_free(p->content);
+
+    etch_free(p);
+    list->count--; 
+    return 0;
+}
+

Added: incubator/etch/trunk/binding-c/runtime/c/src/common/etch_natarray.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/common/etch_natarray.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/common/etch_natarray.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/common/etch_natarray.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,592 @@
+/* $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_natarray.c  
+ * etch_nativearray implementation
+ * does allocation and subscripting for n-dimensional arrays stored as a single
+ * byte vector, to overcome the well-known C compiler issues with passing around
+ * multi dimensioned arrays when the low order dimension is not known at compile
+ * time. the mapping here from byte vector to array tests out as k&r compliant,
+ * this is verified by constructing from a static array using new_nativearray_from
+ * and testing that the get methods return the same result as statically indexed
+ * array items. as it stands, this code handles a max of 3 dimensions. it can be 
+ * generalized to n dimensions, however the caller would have to allocate, populate, 
+ * and pass arrays of subscripts for this to happen.
+ */
+
+#include <stdio.h>
+#include "etch_global.h"
+
+etch_nativearray* init_nativearray 
+    (unsigned short, const size_t, const int, const int, const int, const int);
+int  etch_nativearray_put1 (etch_nativearray*, void*, int); 
+int  etch_nativearray_put2 (etch_nativearray*, void*, int, int); 
+int  etch_nativearray_put3 (etch_nativearray*, void*, int, int, int); 
+int  etch_nativearray_get1 (etch_nativearray*, void*, int); 
+int  etch_nativearray_get2 (etch_nativearray*, void*, int, int); 
+int  etch_nativearray_get3 (etch_nativearray*, void*, int, int, int); 
+int  etch_nativearray_set_content_type(etch_nativearray*);
+
+
+/*
+ * new_nativearray() 
+ * etch_nativearray constructor
+ * note that when creating arrays, the dimensions are passed low-order first,
+ * so for x[2][3][4], dim0 is 4, dim1 is 3, dim2 is 2. for y[7][9], dim0 is 9,
+ * dim1 is 7, and dim2 is zero of course.
+ */
+etch_nativearray* new_nativearray (unsigned short class_id, const size_t itemsize,  
+    const int numdims, const int dim0, const int dim1, const int dim2)
+{
+    etch_nativearray* newarray = init_nativearray(class_id, itemsize, numdims, dim0, dim1, dim2);
+    if (NULL == newarray) return NULL;
+
+    newarray->values = etch_malloc(newarray->bytecount, ETCHTYPEB_BYTES);
+    memset(newarray->values, 0, newarray->bytecount);
+    newarray->is_content_owned = TRUE;
+  
+    etch_nativearray_set_content_type(newarray);
+    return newarray;      
+}
+
+
+/*
+ * new_nativearray_from() 
+ * etch_nativearray constructor from existing byte vector
+ * @param values source array, caller retains ownership.
+ */
+etch_nativearray* new_nativearray_from (void* values, unsigned short class_id, const size_t itemsize, 
+    const int numdims, const int dim0, const int dim1, const int dim2)
+{
+    etch_nativearray* newarray = init_nativearray(class_id, itemsize, numdims, dim0, dim1, dim2);
+    if (NULL == newarray) return NULL;
+
+    newarray->values = values;
+    newarray->is_content_owned = FALSE;
+
+    etch_nativearray_set_content_type(newarray);
+    return newarray;      
+}
+
+
+/*
+ * new_nativearray_of() 
+ * etch_nativearray constructor for array of objects of specified type and class
+ */
+etch_nativearray* new_nativearray_of 
+   (unsigned short content_obj_type, unsigned short content_class_id,  
+    const int numdims, const int dim0, const int dim1, const int dim2)
+{
+    etch_nativearray* newarray = init_nativearray
+       (CLASSID_ARRAY_OBJECT, sizeof(void*), numdims, dim0, dim1, dim2);
+    if (NULL == newarray) return NULL;
+
+    newarray->content_obj_type = content_obj_type;
+    newarray->content_class_id = content_class_id;
+    return newarray;      
+}
+
+
+
+/*
+ * init_nativearray() 
+ * etch_nativearray private constructor
+ * assumes max number of dimensions is 3
+ */
+etch_nativearray* init_nativearray (unsigned short class_id, const size_t itemsize,  
+    const int numdims, const int dim0, const int dim1, const int dim2)
+{
+    etch_nativearray* newarray = NULL;
+    int i,j;
+    if (numdims < 1 || itemsize < 1) return NULL;
+    if (numdims > 1 && dim1 < 1)     return NULL;
+    if (numdims > 2 && dim2 < 1)     return NULL;
+
+    newarray = newarray = (etch_nativearray*) new_object
+        (sizeof(etch_nativearray), ETCHTYPEB_NATIVEARRAY, class_id);
+
+    newarray->numdims  = numdims;
+    newarray->itemsize = itemsize;
+
+    /* dimension array contains the array dimensions, 
+     * e.g., for x[2][3][4], [0] is 4, [1] is 3, [2] is 2 
+     */
+    newarray->dimension[0] = dim0;
+    newarray->dimension[1] = numdims > 1? dim1: 0;
+    newarray->dimension[2] = numdims > 2? dim2: 0;
+
+    /* dimsize array contains size in bytes of the next lower dimension, 
+     * stored so that the values need not be calculated on each array access. 
+     * [0] is item size, so for int x[5][7][9], [0] is sizeof(int), 
+     * [1] is 9*sizeof(int), [2] is 7*9*sizeof(int)
+     */
+    newarray->dimsize[0] = itemsize;
+    newarray->bytecount  = itemsize * dim0;
+
+    for(i = 1, j = 0; i < numdims; i++, j++)
+    {
+        newarray->dimsize[i] = newarray->dimension[j] * newarray->dimsize[j];
+        newarray->bytecount *= newarray->dimension[i];
+    }
+
+    newarray->clone   = clone_null;
+    newarray->destroy = destroy_nativearray;  
+
+    newarray->put1 = etch_nativearray_put1;
+    newarray->put2 = etch_nativearray_put2;
+    newarray->put3 = etch_nativearray_put3;
+    newarray->get1 = etch_nativearray_get1;
+    newarray->get2 = etch_nativearray_get2;
+    newarray->get3 = etch_nativearray_get3;
+
+    return newarray;      
+}
+
+
+/**
+ * destroy_nativearray_content()
+ * destroy nativearray's content vector.
+ * return -1 if content not owned by nativearray and therefore not destroyed;
+ * otherwise return zero, regardless of whether content was null.
+ */
+int destroy_nativearray_content(etch_nativearray* a)
+{
+    int  result = 0;
+    if  (!is_etchobj_static_content(a) && a->is_content_owned)
+         etch_free(a->values);  /* OK if values null */  
+    else result = -1;
+    return result;
+}
+
+
+/**
+ * destroy_nativearray()
+ * etch_nativearray destructor
+ */
+int destroy_nativearray(etch_nativearray* a) 
+{
+    if (a->refcount > 0 && --a->refcount > 0) return -1;  
+    if (a->is_content_owned && !is_etchobj_static_content(a)) 
+        destroy_nativearray_content(a);
+    destroy_objectex((objmask*)a);
+    return 0;
+}
+
+
+/*
+ * new_subarray() 
+ * construct and return subaarray[i] of this array.
+ * subarray points into parent content and so does not own its content
+ */
+etch_nativearray* new_subarray(etch_nativearray* a, const int i) 
+{
+    etch_nativearray* subarray = NULL;
+    const int sub_numdims = a->numdims - 1;
+
+    if (a->numdims > 1 && i < (int) a->dimension[sub_numdims]) 
+    {   
+        const size_t sub_bytelen = a->dimsize[sub_numdims];
+        const size_t vector_offset = i * sub_bytelen;
+        byte* subvector = (byte*) a->values + vector_offset;
+
+        subarray = new_nativearray_from(subvector, 
+            a->class_id, (int) a->itemsize, sub_numdims,  
+            (int) a->dimension[0], (int) a->dimension[1], 0);
+
+        subarray->bytecount = sub_bytelen;
+        subarray->content_obj_type = a->content_obj_type;
+        subarray->content_class_id = a->content_class_id;
+        subarray->is_content_owned = a->is_content_owned;
+
+        subarray->counts[0] = a->counts[0]; /* user-maintained counts */  
+        subarray->counts[1] = a->counts[1];  
+        subarray->counts[2] = 0;
+    }
+
+    return subarray;
+}
+
+
+/*
+ * etch_nativearray_assign_to() 
+ * assign array b to array a, if legal to do so.
+ */
+etch_nativearray* etch_nativearray_assign_to(etch_nativearray* a, etch_nativearray* b)
+{ 
+    if (!is_etch_nativearray(a) || !is_etch_nativearray(b)) return NULL;
+
+    /* arrays must be either of same type, or the left side an array of 
+     * object; and the dimensionalities of the two arrays must be the same.
+     */
+    if(((a->class_id != b->class_id) && (a->class_id != CLASSID_ARRAY_OBJECT))    
+     || (a->numdims  != b->numdims))    
+         return NULL;            
+      
+    destroy_nativearray_content(a);    /* destroy a content if owned */
+
+    a->values    = b->values;          /* assign b content to a */
+    a->itemsize  = b->itemsize;
+    a->bytecount = b->bytecount;      
+    memcpy(a->dimension,  b->dimension, sizeof(a->dimension));
+    memcpy(a->dimsize,    b->dimsize,   sizeof(a->dimsize));
+    memcpy(a->counts,     b->counts,    sizeof(a->counts)); 
+    a->content_obj_type = b->content_obj_type;     
+    a->content_class_id = b->content_class_id;  
+    a->is_content_owned = FALSE;       /* b still owns array content */
+    a->is_copy = TRUE; 
+    return a;
+}
+
+
+/*
+ * etch_nativearray_get_element() 
+ * return element[i] of specified array, which, if array is multi-dimensioned,
+ * will be another native array, otherwise an etch object. for example, if
+ * the supplied array is byte[2][4], a native array of byte[4] is returned.
+ * if the supplied array is byte[4], an etch_byte object is returned.
+ * returned subarrays do not own content, their content references the content
+ * of their parent.
+ */
+objmask* etch_nativearray_get_element(etch_nativearray* a, const int i) 
+{
+    int result = 0;
+    objmask* wrapped_element = NULL;
+    etch_nativearray* subarray = NULL;
+
+    const int sub_numdims = a->numdims - 1;
+    if (sub_numdims < 0) return NULL;
+
+    if (sub_numdims > 0) 
+        return (objmask*) new_subarray(a, i);
+
+    result = etch_nativearray_get_wrapped_component(a, i, &wrapped_element);
+
+    return wrapped_element;
+}
+
+
+/*
+ * etch_nativearray_set_content_type() 
+ * set content_obj_type and content_class_id based on array class_id.
+ * returns zero if content type was set, otherwise -1
+ */
+int etch_nativearray_set_content_type(etch_nativearray* a)
+{
+    unsigned short obj_type = 0;
+    int result = 0;
+
+    switch(a->class_id) 
+    {
+        case CLASSID_ARRAY_BYTE:    obj_type = ETCHTYPEB_BYTE;   break;
+        case CLASSID_ARRAY_BOOL:    obj_type = ETCHTYPEB_BOOL;   break;
+        case CLASSID_ARRAY_INT8:    obj_type = ETCHTYPEB_INT8;   break;
+        case CLASSID_ARRAY_INT16:   obj_type = ETCHTYPEB_INT16;  break;
+        case CLASSID_ARRAY_INT32:   obj_type = ETCHTYPEB_INT32;  break;
+        case CLASSID_ARRAY_INT64:   obj_type = ETCHTYPEB_INT64;  break;
+        case CLASSID_ARRAY_FLOAT:   obj_type = ETCHTYPEB_IEEE32; break;
+        case CLASSID_ARRAY_DOUBLE:  obj_type = ETCHTYPEB_IEEE64; break;
+    }
+
+    if (obj_type)
+    {   a->content_obj_type = obj_type;
+        a->content_class_id = CLASSID_UNWRAPPED;
+    }
+    else switch(a->class_id) 
+    {
+        case CLASSID_ARRAY_OBJECT: 
+            a->content_obj_type = ETCHTYPEB_ETCHOBJECT; 
+            a->content_class_id = CLASSID_OBJECT;
+            break;
+
+        case CLASSID_ARRAY_STRING:  
+            a->content_obj_type = ETCHTYPEB_STRING; 
+            a->content_class_id = CLASSID_STRING;
+            break;
+
+        default:
+            result = -1; /* indicates content type not set */
+    }
+    
+    return result;
+}
+
+
+/**
+ * put1()
+ * insert item to singly dimensioned array
+ * array access can be generalized by passing an array of subscripts; however
+ * since we are currently handling max 3 dimensions, the calling sequence is 
+ * much simpler when we have separate accessors for each dimensionality.
+ */
+int etch_nativearray_put1(etch_nativearray* a, void* value, int i) 
+{
+    size_t offset = etch_nativearray_off1(a, i);
+    if (value == NULL || offset < 0) return -1;
+    memcpy((byte*)a->values + offset, value, a->itemsize); 
+    return 0;
+}
+
+
+/**
+ * put2()
+ * insert item to 2-dimensional array
+ */
+int etch_nativearray_put2(etch_nativearray* a, void* value, int i, int j) 
+{
+    size_t offset = etch_nativearray_off2(a, i, j);
+    if (value == NULL || offset < 0) return -1;
+    memcpy((byte*)a->values + offset, value, a->itemsize);  
+    return 0;
+}
+
+
+/**
+ * put3()
+ * insert item to 3-dimensional array
+ */
+int etch_nativearray_put3(etch_nativearray* a, void* value, int i, int j, int k) 
+{
+    size_t offset = etch_nativearray_off3(a, i, j, k);
+    if (value == NULL || offset < 0) return -1;
+    memcpy((byte*)a->values + offset, value, a->itemsize); 
+    return 0;
+}
+
+
+/**
+ * get1()
+ * access and return item from singly dimensioned array
+ */
+int etch_nativearray_get1(etch_nativearray* a, void* value, int i) 
+{
+    size_t offset = etch_nativearray_off1(a, i);
+    if (value == NULL || offset < 0) return -1;
+    memcpy(value, (byte*)a->values + offset, a->itemsize); 
+    return 0;
+}
+
+
+/**
+ * get2()
+ * access and return item from 2-dimensional array
+ */
+int etch_nativearray_get2(etch_nativearray* a, void* value, int i, int j) 
+{
+    size_t offset = etch_nativearray_off2(a, i, j);
+    if (value == NULL || offset < 0) return -1;
+    memcpy(value, (byte*)a->values + offset, a->itemsize); 
+    return 0;
+}
+
+
+/**
+ * get3()
+ * access and return item from 3-dimensional array
+ */
+int etch_nativearray_get3(etch_nativearray* a, void* value, int i, int j, int k) 
+{
+    size_t offset = etch_nativearray_off3(a, i, j, k);
+    if (value == NULL || offset < 0) return -1;
+    memcpy(value, (byte*)a->values + offset, a->itemsize); 
+    return 0;
+}
+
+
+/*
+ * etch_nativearray_off1() 
+ * calculate byte offset into byte vector for a 1-dimension array
+ */
+size_t etch_nativearray_off1(etch_nativearray* a, int i)
+{
+    size_t offset = 0;    
+    if (i >= (int) a->dimension[0] || i < 0) return -1; 
+
+    offset = i * a->dimsize[0];
+    return offset;
+}
+
+
+/*
+ * etch_nativearray_off2() 
+ * calculate byte offset into byte vector for a 2-dimension array
+ */
+size_t etch_nativearray_off2(etch_nativearray* a, int i, int j)
+{
+    size_t offset = 0;    
+    if ((i >= (int) a->dimension[1] || i < 0)  
+     || (j >= (int) a->dimension[0] || j < 0)) return -1; 
+
+    offset = (i * a->dimsize[1]) + (j * a->dimsize[0]);
+    return offset;
+}
+
+
+/*
+ * etch_nativearray_off3() 
+ * calculate byte offset into byte vector for a 3-dimension array
+ */
+size_t etch_nativearray_off3(etch_nativearray* a, int i, int j, int k)
+{
+    size_t offset = 0;    
+    if ((i >= (int) a->dimension[2] || i < 0)  
+     || (j >= (int) a->dimension[1] || j < 0)   
+     || (k >= (int) a->dimension[0] || k < 0)) return -1; 
+
+    offset = (i * a->dimsize[2]) + (j * a->dimsize[1]) + (k * a->dimsize[0]);
+    return offset;
+}
+
+
+/**
+ * etch_nativearray_get_component_type()
+ * java.lang.class.getcomponenttype returns the class of an array's members. 
+ * we instead identify the etch object type and class id of the array's members, 
+ * returning results in the passed parameter struct reference. 
+ */
+int etch_nativearray_get_component_type
+   (etch_object* classobj, etch_component_type_params* p)
+{
+    int result = 0;
+    if (!p) return -1;
+    memset(p, 0, sizeof(etch_component_type_params));
+    if (!is_etch_nativearray(classobj)) return -1;  
+
+    p->origl_array    = (etch_nativearray*) classobj;
+    p->origl_obj_type = p->origl_array->content_obj_type;
+    p->origl_class_id = p->origl_array->content_class_id;
+    p->dimensions     = p->origl_array->numdims;
+
+    p->final_array    = p->origl_array;
+    p->final_obj_type = p->origl_obj_type;
+    p->final_class_id = p->origl_class_id;
+
+    /* we could have here an array of (pointers to) array. recurse the array 
+     * until array content is no longer array.
+     */
+    while(is_etch_nativearray(p->final_obj_type))
+    {   
+        /* the content of the current array is array,         
+         * so peek at item[0] in this array of arrays */
+        etch_nativearray* content_array = p->final_array->bytecount >= sizeof(void*)?
+           (etch_nativearray*) ((etch_nativearray**) p->final_array->values)[0]: NULL;
+
+        if (!is_etch_nativearray(content_array))
+        {   result = -1;/* sanity check, [0] not array, however content */
+            break;      /* type indicated array, logic error, exception */
+        }
+
+        p->final_array    = content_array; 
+        p->final_obj_type = content_array->content_obj_type;
+        p->final_class_id = content_array->content_class_id;
+        if (is_etch_nativearray(p->final_obj_type))
+            p->dimensions += p->final_array->numdims; 
+    } 
+
+    return result;
+}
+
+
+/** 
+ * etch_nativearray_get_wrapped_component()
+ * get wrapped component[i] from the single-dimensioned native array.
+ * caller owns returned object.
+ * todo: test that if array content was wrapped, the is_value_owned
+ * setting is sufficient for tranparent memory management of returned object.
+ */
+int etch_nativearray_get_wrapped_component(etch_nativearray* a, const int i, objmask** out)
+{
+    const int numentries = (int) a->dimension[0];
+    const int is_wrapped_content = a->content_class_id != 0;
+    int result = 0;
+    union
+    { char  vbyte; short  vint16; int   vint32; int64 vint64; 
+      float vfloat;double vdouble;void* vaddr;  int64 all;
+    } v;
+
+    if (a->numdims != 1 || i >= numentries) return -1;
+    v.all = 0;
+
+    if (is_wrapped_content)
+    {   /* content of the native array is wrapped, e.g, etch_object*,   
+         * so we return the item as is */   
+         result = a->get1(a, &v.vaddr, i);
+         *out = v.vaddr;        
+    }
+    else switch(a->content_obj_type)
+    {   /* content of the native array is unwrapped, e.g, int[], so we wrap   
+         * the array item with an etch object prior to returning it */                  
+        case ETCHTYPEB_BYTE: 
+             result = a->get1(a, &v.vbyte, i);
+             *out = (objmask*) new_byte(v.vbyte);
+             break;
+  
+        case ETCHTYPEB_BOOL: 
+             result = a->get1(a, &v.vbyte, i);
+             *out = (objmask*) new_boolean(v.vbyte);
+             break;   
+
+        case ETCHTYPEB_INT8: 
+             result = a->get1(a, &v.vbyte, i);
+             *out = (objmask*) new_int8(v.vbyte);
+             break; 
+     
+        case ETCHTYPEB_INT16:  
+             result = a->get1(a, &v.vint16, i);
+             *out = (objmask*) new_int16(v.vint16);
+             break; 
+
+        case ETCHTYPEB_INT32: 
+             result = a->get1(a, &v.vint32, i);
+             *out = (objmask*) new_int32(v.vint32);
+             break; 
+
+        case ETCHTYPEB_INT64: 
+             result = a->get1(a, &v.vint64, i);
+             *out = (objmask*) new_int64(v.vint64);
+             break;  
+
+        case ETCHTYPEB_IEEE32:  
+             result = a->get1(a, &v.vfloat, i);
+             *out = (objmask*) new_float(v.vfloat);
+             break;      
+
+        case ETCHTYPEB_IEEE64:
+             result = a->get1(a, &v.vdouble, i);
+             *out = (objmask*) new_double(v.vdouble);
+             break; 
+
+        case ETCHTYPEB_STRING: 
+             result = a->get1(a, &v.vaddr, i);
+             *out = (objmask*) new_string(v.vaddr, ETCH_ENCODING_UTF16);
+             break; 
+
+        default: /* item is an anonymous pointer to a value owned by caller */
+        {    etch_object* wrapper = NULL;               
+             result  = a->get1(a, &v.vaddr, i);  
+             wrapper = new_etch_object(a->content_class_id, v.vaddr); 
+             /* we clear is_value_owned so value will not be freed by dtor */
+             wrapper->is_value_object = wrapper->is_value_owned = FALSE;
+             *out = (objmask*) wrapper;
+        } 
+
+    }  /* switch(a->content_obj_type) */ 
+
+    return result;
+}
+

Added: incubator/etch/trunk/binding-c/runtime/c/src/common/etch_objects.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/common/etch_objects.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/common/etch_objects.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/common/etch_objects.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,259 @@
+/**
+ * etch_objects.c 
+ * etch type object wrappers construction
+ */
+
+#include <stdio.h>
+#include "etch_objects.h"
+#include "etchmem.h"
+#include "etchrun.h"
+#include "etch_arraylist.h"
+
+
+/**
+ * new_etch_primitive_object()
+ * constructor for an etchobject wrapper for a primitive value
+ * TODO LOSE
+ */
+etchobject* new_etchobject_primitive(const int objtype)
+{
+    etchobject* newobj = new_etchobject(objtype);
+    // newobj->is_static_data = 0; // *****************
+    return newobj;
+}
+
+/**
+ * new_etch_int32()
+ * constructor for ETCH_INT32, a boxed 32-bit integer
+ */
+ETCH_INT32* new_etch_int32(const int value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_INT32);
+    newobj->value_int32 = value;
+    newobj->size = sizeof(int);
+    return newobj;
+}
+
+/**
+ * new_etch_int8()
+ * constructor for ETCH_INT8, a boxed 8-bit integer
+ */
+ETCH_INT8* new_etch_int8(const signed char value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_INT8);
+    newobj->value_int8 = value;
+    newobj->size = sizeof(char);
+    return newobj;
+}
+
+/**
+ * new_etch_int16()
+ * constructor for ETCH_INT16, a boxed 16-bit integer
+ */
+ETCH_INT16* new_etch_int16(const short value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_INT16);
+    newobj->value_int16 = value;
+    newobj->size = sizeof(short);
+    return newobj;
+}
+
+
+/**
+ * new_etch_int64()
+ * constructor for ETCH_INT64, a boxed 64-bit integer
+ */
+ETCH_INT64* new_etch_int64(const int64 value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_INT64);
+    newobj->value_int64 = value;
+    newobj->size = sizeof(int64);
+    return newobj;
+}
+
+/**
+ * new_etch_byte()
+ * constructor for ETCH_BYTE, a boxed unsigned char
+ */
+ETCH_BYTE* new_etch_byte(const unsigned char value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_BYTE);
+    newobj->value_byte = value;
+    newobj->size = sizeof(char);
+    return newobj;
+}
+
+/**
+ * new_etch_bool()
+ * constructor for ETCH_BOOL, a boxed unsigned char
+ */
+
+ETCH_BOOL* new_etch_bool(const unsigned char value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_BOOL);
+    newobj->value_byte = value? TRUE: FALSE;
+    newobj->size = sizeof(char);
+    return newobj;
+}
+
+/**
+ * new_etch_ieee32()
+ * constructor for ETCH_IEEE32, a boxed float
+ */
+ETCH_IEEE32* new_etch_ieee32(const float value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_IEEE32);
+    newobj->value_ieee32 = value;
+    newobj->size = sizeof(float);
+    return newobj;
+}
+
+/**
+ * new_etch_ieee64()
+ * constructor for ETCH_IEEE64, a boxed float
+ */
+ETCH_IEEE64* new_etch_ieee64(const double value)
+{
+    etchobject* newobj = new_etchobject_primitive(ETCHTYPE_BOXED_IEEE64);
+    newobj->value_ieee64 = value;
+    newobj->size = sizeof(double);
+    return newobj;
+}
+
+/**
+ * new_etch_string()
+ * constructor for ETCH_STRING, a boxed array of wchar_t
+ */
+ETCH_STRING* new_etch_string(const wchar_t* value)
+{
+    etchobject* newobj = NULL;
+    wchar_t* newval = NULL;
+    size_t bytelen = 0;
+    size_t numchars = value? wcslen(value) + 1: 0;
+    bytelen = sizeof(wchar_t) * numchars;
+
+    newval = etch_malloc (bytelen, ETCHTYPEB_BYTES);
+    memcpy(newval, value, bytelen); 
+
+    newobj = new_etchobject(ETCHTYPE_BOXED_STRING);
+    newobj->value_ptr_to = newval;
+    newobj->size = bytelen;
+    return newobj;
+}
+
+
+/**
+ * new_etch_static_string()
+ * constructor for ETCH_STRING, a boxed array of wchar_t
+ * specified string will not be freed when the object is destroyed
+ */
+ETCH_STRING* new_etch_static_string(const wchar_t* value)
+{
+    etchobject* newobj = NULL;
+    //size_t bytelen = 0;
+    //size_t numchars = value? wcslen(value) + 1: 0;
+    //bytelen = sizeof(wchar_t) * numchars;
+
+    //newobj = new_etchobject(ETCHTYPE_BOXED_STRING);
+    //newobj->value_ptr_to = (wchar_t*)value;
+    //newobj->size = bytelen;
+    //newobj->is_static_data = TRUE;
+    return newobj;
+}
+
+
+/**
+ * destroy_boxed_arraylist(()
+ * destructor for ETCH_ARRAYLIST, a boxed etch_arraylist.
+ */
+void destroy_boxed_arraylist(ETCH_ARRAYLIST* thisp)
+{
+  //if (!thisp->is_static_data && thisp->value_ptr_to)   
+  //    arraylist_destroy((etch_arraylist*)thisp->value_ptr_to, TRUE); 
+
+  //if (!thisp->is_static_object)
+  //    etch_free(thisp);
+}
+
+
+/**
+ * clone_boxed_arraylist()
+ */
+ETCH_ARRAYLIST* clone_boxed_arraylist(ETCH_ARRAYLIST* thisp)
+{
+    int i = 0, result = 0;
+    void* content = NULL;
+    etchobject* newobj = NULL;
+    //etch_arraylist* newlist = NULL, *oldlist = NULL;
+    //if (thisp == NULL) return NULL;
+
+    //if (thisp->is_static_data) /* if static string return it */
+    //    return thisp->value_ptr_to;
+    //                           /* null if nothing to copy */
+    //if (thisp->value_ptr_to == NULL || thisp->size < 1) 
+    //    return NULL;  
+
+    //oldlist = (etch_arraylist*) thisp->value_ptr_to;
+    //newlist = new_arraylist(oldlist->count, oldlist->delta);
+    //newlist->is_readonly  = oldlist->is_readonly;
+    //newlist->content_type = oldlist->content_type;
+
+    //while((result == 0) && (NULL != (content = arraylist_get(oldlist, i++)))) 
+    //       result = arraylist_add(newlist, content);
+
+    //newobj = new_etchobject(ETCHTYPE_BOXED_ARRAYLIST);
+    //memcpy(newobj, thisp, sizeof(etchobject));
+    //newobj->value_ptr_to = newlist;
+  
+    return newobj;     
+}
+
+
+
+/**
+ * new_etch_arraylist(initsize, delta)
+ * constructor for ETCH_ARRAYLIST, a boxed etch_arraylist.
+ * initsize: initial number of entries allocated, default configured.
+ * deltsize: number of entries added upon expansion, default initsize.
+ * is_readonly: if TRUE, memory for arraylist content will not be freed
+ * upon invoking destroy() (of course, more control could be exerted 
+ * by operating on the underlying etch_arraylist directly).
+ */
+ETCH_ARRAYLIST* new_etch_arraylist
+    (const unsigned initsize, const unsigned deltsize, const unsigned is_readonly)
+{
+    etchobject* newobj = NULL;
+    //i_etchobject* vtab = NULL;
+    //const int VTAB_KEY = ETCHTYPEB_ARRAYLIST;
+
+    //etch_arraylist* list = new_arraylist(initsize, deltsize);
+    //if (NULL == list) return NULL; 
+
+    //newobj = new_etchobject(ETCHTYPE_BOXED_ARRAYLIST);
+    //newobj->value_ptr_to = list;
+    //newobj->size = list->size; /* TODO size as elsewhere */
+    //list->is_readonly = is_readonly != 0; /* static content indicator */
+
+    //vtab = cache_find(VTAB_KEY, 0); 
+
+    //if(!vtab)  /* cache the vtable for this object type */
+    //{  
+    //    vtab = new_vtable(newobj->vtab, ETCHOBJ_VTABSIZE, ETCHTYPEB_VTABLE, 0);
+
+    //    /* function overrides */
+    //    vtab->destroy = destroy_boxed_arraylist;   
+    //    vtab->clone   = clone_boxed_arraylist;
+    //    
+    //    vtab->vtab = newobj->vtab; /* chain parent vtable to override vtable */
+
+    //    cache_insert(VTAB_KEY, vtab, 0); /* cache the new vtable */
+    //} 
+
+    //newobj->vtab = vtab;  /* set override vtable */
+    return newobj;
+}
+
+
+
+
+

Added: incubator/etch/trunk/binding-c/runtime/c/src/common/etchexcp.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/common/etchexcp.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/common/etchexcp.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/common/etchexcp.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,487 @@
+/* $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. 
+ */ 
+
+/*
+ * etchexcp.c -- exception objects native and boxed  
+ */
+
+#include <stdio.h>
+#include "etch_encoding.h"
+#include "etchexcp.h"
+#include "etch_global.h"
+#pragma warning (disable:4996)
+
+
+/**
+ * etch_throw()
+ * "throw" specified exception on specified object, meaning create an exception 
+ * and store it in the specified object's return value.
+ * type: arbitrary exception type, not edited. if a known type and text is not 
+ * supplied, attempt is made to locate and supply default text for that type.
+ * text: optional text descriptive of the exception.
+ * bitwise flags: 
+ * ETCHEXCP_COPYTEXT: make a copy of supplied text and free it on destroy
+ * ETCHEXCP_FREETEXT: at destroy time, free the exception text memory
+ */
+objmask* etch_throw(objmask* obj, const excptype type, wchar_t* text, unsigned flags)
+{
+    int result = 0;
+    if (!obj) return NULL;
+
+    if(!obj->result)
+        obj->result = new_etchresult(0, 0);
+
+    if (obj->result->exception)
+        destroy_exception(obj->result->exception);
+
+    obj->result->exception = new_exception(type, text, flags);
+    return obj;
+} 
+
+
+/**
+ * etch_throwex()
+ * throw specified exception.
+ * same as etch_throw but with etch_result parameters specified as well.
+ */
+objmask* etch_throwex(objmask* obj, const excptype type, wchar_t* text,  
+    unsigned flags, const int resultcode, const int reasoncode) 
+{
+    if (NULL == etch_throw(obj, type, text, flags)) return NULL;
+    obj->result->resultcode = resultcode;
+    obj->result->reasoncode = reasoncode;
+    return obj;
+} 
+
+
+/*
+ * new_exception() 
+ * instantiate a native exception object.
+ * this is not an etch object, it is a raw struct, see new_etch_exception()
+ * bitwise flags: 
+ *   ETCHEXCP_COPYTEXT:  make a copy of supplied text and free it on destroy
+ *   ETCHEXCP_FREETEXT:  at destroy time, free the exception text memory
+ *   ETCHEXCP_UNCHECKED: exception is unchecked
+ */
+etchexception* new_exception(const excptype type, wchar_t* text, const unsigned flags)
+{
+    size_t numchars = 0;
+    etchexception* excp = etch_malloc(sizeof(etchexception), ETCHTYPEB_EXCEPTION);
+    memset(excp, 0, sizeof(etchexception));
+    excp->excptype = type;
+    excp->flags    = flags;
+
+    if (text && !flags) /* if text without flags, default to copy text */
+        excp->flags = ETCHEXCP_COPYTEXT;
+    else
+    if(!text) /* if no text, get default text and clear copy and free flags */
+    {   text = default_excptext(type);
+        excp->flags &= ~(ETCHEXCP_FREETEXT | ETCHEXCP_COPYTEXT);  
+    }
+
+    if (text) /* calculate byte length of text */
+    {   numchars = wcslen(text) + 1;
+        excp->textlen  = sizeof(wchar_t) * numchars;
+    }
+    
+    if (text && (flags & ETCHEXCP_COPYTEXT))
+    {   /* if asked to make a copy of the text, do so */
+        excp->excptext = etch_malloc(excp->textlen, ETCHTYPEB_STRING);
+        wcscpy_s(excp->excptext, numchars, text); 
+        excp->flags |= ETCHEXCP_FREETEXT; /* indicate free on destroy */
+    }    
+    else excp->excptext = text; /* ETCHEXCP_FREETEXT may or may not be set */
+
+    /* etch_malloc an ansi copy for display */
+    if (0 == etch_unicode_to_ansi (&excp->ansitext, excp->excptext))
+        excp->atxtlen = strlen(excp->ansitext);
+
+    if (type >= EXCPTYPE_CHECKED_START)  /* mark checked excp as such */
+        excp->flags |= ETCHEXCP_CHECKED;
+        
+    return excp;
+}
+
+
+/**
+ * destroy_etch_exception()
+ */
+int destroy_etch_exception(etch_exception* ee)
+{   
+    if (ee->refcount > 0 && --ee->refcount > 0) return -1;  
+
+    if (!is_etchobj_static_content(ee))
+        destroy_exception(ee->value);
+
+    return destroy_objectex((objmask*) ee);
+}
+
+
+/**
+ * clone_etch_exception()
+ */
+etch_exception* clone_etch_exception (etch_exception* ee)
+{   
+    etch_exception* newobj = NULL;
+    etchexception* excp = ee? (etchexception*) ee->value: NULL;
+    if (!excp) return NULL;
+    newobj = new_etch_exception (excp->excptype, excp->excptext, ETCHEXCP_COPYTEXT);
+    return newobj;
+}
+
+
+/**
+ * new_etch_exception()
+ * constructor for wrapped exception
+ */ 
+etch_exception* new_etch_exception(const excptype type, wchar_t* text, 
+    const unsigned flags) 
+{
+    etch_exception* newobj = (etch_exception*) new_object
+        (sizeof(struct etch_exception), ETCHTYPEB_EXCEPTION, CLASSID_EXCEPTION);
+
+    newobj->value = new_exception(type, text, flags);
+
+    newobj->destroy = destroy_etch_exception;
+    newobj->clone   = clone_etch_exception;
+
+    return newobj;
+}
+
+
+/* builtin exception text */
+const wchar_t* excptext_excp    = L"etch"; 
+const wchar_t* excptext_io      = L"I/O";
+const wchar_t* excptext_auth    = L"authorization";
+const wchar_t* excptext_runtime = L"etch runtime";
+const wchar_t* excptext_nullptr = L"null pointer";
+const wchar_t* excptext_arg     = L"illegal argument";  
+const wchar_t* excptext_unsupop = L"unsupported operation"; 
+const wchar_t* excptext_internal= L"internal error";
+const wchar_t* excptext_notfound= L"not found";
+
+
+/*
+ * default_excptext() 
+ * find and return default text for exception type
+ */
+wchar_t* default_excptext(const excptype type)
+{
+    wchar_t* text = NULL;
+
+    switch(type)
+    {   
+       case EXCPTYPE_GENERIC:       text = (wchar_t*) excptext_excp;    break;  
+       case EXCPTYPE_ETCHRUNTIME:   text = (wchar_t*) excptext_runtime; break;  
+       case EXCPTYPE_ETCHAUTH:      text = (wchar_t*) excptext_auth;    break;   
+       case EXCPTYPE_IO:            text = (wchar_t*) excptext_io;      break;   
+       case EXCPTYPE_NULLPTR:       text = (wchar_t*) excptext_nullptr; break;    
+       case EXCPTYPE_ILLEGALARG:    text = (wchar_t*) excptext_arg;     break; 
+       case EXCPTYPE_UNSUPPORTEDOP: text = (wchar_t*) excptext_unsupop; break;
+       case EXCPTYPE_INTERNALERR:   text = (wchar_t*) excptext_internal;break;
+       case EXCPTYPE_NOTFOUND:      text = (wchar_t*) excptext_notfound;break;
+    }
+
+    return text;
+}
+
+
+/*
+ * destroy_exception()
+ * free memory for specified native exception object
+ */
+void destroy_exception (etchexception* excp)
+{
+    if(!excp) return;  /* text may be static or freed elsewhere */
+
+    if (excp->flags & ETCHEXCP_FREETEXT)
+    {   ETCHOBJ_FREE(excp->excptext);   /* free exception text */ 
+    }
+
+    /* always allocated in ctor, never passed in */
+    ETCHOBJ_FREE(excp->ansitext);
+   
+    etch_free(excp);   /* free exception wrapper */
+}
+
+
+/*
+ * get_excpobj()
+ * create and return an etchobject for the sole purpose of returning an exception.
+ * we might use this functionality where our method returns an object which we have
+ * not yet created, we edit parameters, find them wanting, and wish to throw an 
+ * exception, and need an object in which to return the exception.
+ */ 
+objmask* get_excpobj (int objsize, short obj_type, short class_id,
+    excptype xcptype, wchar_t* xcptext, unsigned flags)
+{
+    objmask* newobj = new_object(objsize, obj_type, class_id);
+    newobj->is_null = TRUE; 
+    etch_throw(newobj, xcptype, xcptext, flags);
+    return newobj;
+} 
+
+
+/*  
+ * get_excptype()
+ * return exception type given result code
+ */
+excptype get_excptype(const results result)
+{
+    excptype xtype;
+    if (result >= 0) return EXCPTYPE_NONE;
+
+    switch(result)
+    {    
+        case ETCHRESULT_EXCPERR_IO:      xtype = EXCPTYPE_IO;            break;
+        case ETCHRESULT_EXCPERR_BADARG:  xtype = EXCPTYPE_ILLEGALARG;    break;
+        case ETCHRESULT_EXCPERR_NULLPTR: xtype = EXCPTYPE_NULLPTR;       break;
+        case ETCHRESULT_EXCPERR_BADOP:   xtype = EXCPTYPE_UNSUPPORTEDOP; break;
+        default: xtype = EXCPTYPE_GENERIC;  
+    }
+    return xtype;
+}
+
+
+/*  
+ * excp_tostring
+ * returns unicode string representation of exception
+ * caller owns returned buffer
+ */
+wchar_t* excp_tostring (etchexception* excp)
+{
+    wchar_t *newbuf = NULL;
+    const wchar_t *x = L"exception ", charlen = sizeof(wchar_t), *space = L" " ;
+    const size_t xbytelen = wcslen(x) * charlen;
+    wchar_t* deftext = default_excptext(excp->excptype);
+    const size_t deftextbytelen = deftext? 
+          wcslen(deftext) * charlen: 0;
+    const size_t excptextbytelen = excp->excptext? 
+          wcslen(excp->excptext) * charlen: 0;
+    wchar_t* excptext 
+           = excptextbytelen? excp->excptext: 
+             deftextbytelen?  deftext:
+             L"generic";
+    const size_t textbytelen = wcslen(excp->excptext) * charlen;
+    const size_t buflen = xbytelen + textbytelen + (3 * charlen);
+
+    newbuf = etch_malloc(buflen, ETCHTYPEB_BYTES);
+    memset(newbuf, 0, buflen);
+    
+    wcscat(newbuf, excptext); /* e.g. "null pointer" */
+    wcscat(newbuf, space);
+    wcscat(newbuf, x);        /* "exception " */
+
+    return newbuf; 
+}
+
+
+/*  
+ * excp_tostringx
+ * returns ascii string representation of exception
+ * caller owns returned buffer
+ */
+char* excp_tostringx(etchexception* excp)
+{
+    char* ansibuf = NULL;
+    wchar_t*  unibuf = excp_tostring(excp);
+    const int result = etch_unicode_to_ansi(&ansibuf, unibuf); 
+    etch_free(unibuf);
+    return ansibuf; 
+}
+
+
+/*  
+ * is_catch_exception()
+ * "catch" exception defined by result code, returning FALSE if no exception.
+ * the etchobject wrapping the exception is returned in the out parameter. 
+ * this object is created if no such object is passed.
+ */
+boolean is_catch_exception(objmask* obj, const int result, objmask** outobj)
+{
+    objmask* excpobj = throw_exception(obj, result);
+
+    if (is_exception(excpobj))
+    {
+        if (outobj) *outobj = excpobj;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+
+/*  
+ * is_catch()
+ * "catch" exception defined by result code, returning FALSE if no exception.
+ * the etchobject wrapping the exception is returned in the out parameter. 
+ * this object is created if no such object is passed.
+ */
+boolean is_catch(objmask* obj, const int result, const int objtype, objmask** outobj)
+{
+    objmask* excpobj = obj? 
+        throw_exception(obj, result):
+        throw_exception_from(objtype, result);
+
+    if (is_exception(excpobj))
+    {
+        if (outobj) *outobj = excpobj;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+
+/*  
+ * catch_exception()
+ * return an etchobject containing the exception mapping to the specified 
+ * result code. an anonymous object is generated if none is supplied.
+ */
+objmask* catch_exception(objmask* obj, const int result)
+{
+    return throw_exception(obj, result);
+}
+
+
+/*  
+ * throw_exception()
+ * return an etchobject of the specified type containing the exception mapping to
+ * the specified result code. an anonymous object is generated if none is supplied.
+ */
+objmask* throw_exception(objmask* obj, const int result)
+{
+    excptype xtype = get_excptype(result);
+    if (obj == NULL) 
+        obj = get_excpobj(sizeof(objmask), ETCHTYPEB_UNDEFINED, 0, xtype, NULL, 0);
+
+    if (xtype != EXCPTYPE_NONE)  
+        etch_throw(obj, xtype, NULL, 0);
+
+    return obj;
+}
+
+
+/*  
+ * throw_exception_from()
+ * generate and return an etch object of the specified type containing the exception
+ * mapping to the specified result code.  
+ */
+objmask* throw_exception_from(const short obj_type, const int result)
+{
+    objmask* obj = NULL;
+    excptype xtype  = get_excptype(result);
+    obj = get_excpobj(sizeof(objmask), obj_type, 0, xtype, NULL, 0);
+    return obj;
+}
+
+
+/*  
+ * throw_from()
+ * generate and return an etchobject of the specified type 
+ * containing the specified exception
+ */
+objmask* throw_from(excptype xtype, const short obj_type, wchar_t* text, unsigned flags)
+{
+    return get_excpobj(sizeof(objmask), obj_type, 0, xtype, text, flags);
+}
+
+
+/*  
+ * etch_rethrow
+ * throw an exception from an existing exception 
+ */
+objmask* etch_rethrow(objmask* target, objmask* source)
+{
+    etchexception* excp = NULL;
+    if (target != NULL)
+        excp = get_exception(source);
+    if (excp == NULL) return throw_from(EXCPTYPE_INTERNALERR, target->obj_type, NULL, 0);
+    
+    return etch_throwex(target, excp->excptype, excp->excptext, excp->flags, 
+                source->result->resultcode, source->result->reasoncode);     
+}
+
+
+/*  
+ * get_etch_exception_from()
+ * returns the etch_exception object if any from the specified etch object.
+ * @return a non-disposable reference to the etch_exception object, or NULL.
+ */
+etch_exception* get_etch_exception_from (objmask* obj)
+{   
+    if (obj && (obj->obj_type == ETCHTYPEB_EXCEPTION)) 
+        return (etch_exception*) obj;
+    return NULL;
+}
+
+
+/*  
+ * get_exception_from
+ * returns the unwrapped etchexception if any from the specified etch object.
+ */
+etchexception* get_exception_from (objmask* obj)
+{   
+    if (NULL == obj) return NULL;
+    if (obj->obj_type == ETCHTYPEB_EXCEPTION) 
+        return (etchexception*) ((etch_exception*) obj)->value;
+    if (obj->result) return obj->result->exception;
+    return NULL;
+}
+
+
+/*  
+ * get_exception_from()
+ * returns a disposable exception object based on the exception contained in
+ * the specified object.
+ */
+etch_exception* new_etch_exception_from (objmask* obj)
+{
+    etch_exception* x = NULL;
+    etchexception* excp = get_exception_from (obj);
+    if (excp)
+        x = new_etch_exception (excp->excptype, excp->excptext, ETCHEXCP_COPYTEXT);
+    return x;
+}
+
+
+/*  
+ * verifyx()
+ * test specified object for specified type, throw specified exception if not
+ */
+objmask* verifyx(objmask* obj, 
+    const unsigned short objtype, const unsigned short classid, excptype xtype)
+{
+    if(!obj)
+        obj = throw_from(xtype, objtype, NULL, 0);
+    else
+    if ((objtype != 0 && obj->obj_type != objtype)
+     || (classid != 0 && obj->class_id != classid)) 
+        etch_throwex(obj, xtype, NULL, 0, -1, 0);
+
+    return obj;
+}
+
+
+
+
+
+
+
+
+

Added: incubator/etch/trunk/binding-c/runtime/c/src/common/etchflexbuf.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/common/etchflexbuf.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/common/etchflexbuf.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/common/etchflexbuf.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,744 @@
+/* $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. 
+ */ 
+
+/*
+ * etchflexbuf.c
+ * flex buffer
+ */
+
+#include "etchflexbuf.h"
+#include "etchobjtypes.h"
+#include "etch_global.h"
+#include "etchlog.h"
+
+#define ETCH_INIT_FLEXBUFSIZE 2048
+#define ETCH_MAX_FLEXBUFSIZE (4*1024*1024)
+
+void    etch_flexbuf_fix_length  (etch_flexbuffer*);
+BOOLEAN etch_flexbuf_ensure_size (etch_flexbuffer*, size_t);
+
+/* 
+ * java binding syntax is confusing and ambiguous so we change it a bit. java 
+ * calls the data region in the buffer "length". since "length" is non-specific,
+ * and there are other "length"s, such as "buffer.length", and "object.length", 
+ * we'll call it "datalen", to mean "meaningful bytes within the buffer". java
+ * also uses "buffer.length", which is the size of the allocated buffer. c of
+ * course does not associate properties with arrays, so we carry an additional
+ * property "bufsize" to indicate the allocated length of the byte array.  
+ */
+
+
+/**
+ * new_flexbuffer()
+ * etch_flexbuffer constructor
+ */
+etch_flexbuffer *new_flexbuffer (size_t bufsize)
+{
+    void *buf;
+    if (bufsize <= 0 || bufsize > ETCH_MAX_FLEXBUFSIZE) bufsize = ETCH_INIT_FLEXBUFSIZE;
+
+    buf = etch_malloc(bufsize, ETCHTYPEB_BYTES);
+    memset(buf, 0, bufsize);
+   
+    return etch_flexbuf_create_bi (buf, bufsize, 0, 0);
+}
+
+
+/**
+ * new_flexwriter_from()
+ * etch_flexbuffer constructor with index set to write
+ */
+etch_flexbuffer *new_flexwriter_from (void *buf, size_t datalen, size_t bufsize) 
+{
+    return new_flexbuffer_from (buf, datalen, bufsize, datalen);       
+}
+
+
+/**
+ * new_flexbuffer_from()
+ * etch_flexbuffer constructor.
+ * @param buf data which is to become the internal buffer. caller relinquishes this memory.
+ * @param datalen length of real data in bytes.
+ * @param bufsize size of buffer in bytes.  
+ * @param buffer index at which to start.
+ */
+etch_flexbuffer *new_flexbuffer_from (void* buf, size_t datalen, size_t bufsize, size_t index)
+{
+    if (bufsize <= 0 || bufsize > ETCH_MAX_FLEXBUFSIZE) bufsize = ETCH_INIT_FLEXBUFSIZE;
+    if (datalen > bufsize || (!buf && datalen)) return NULL;
+    if (NULL == buf) 
+    {   buf = etch_malloc(bufsize, ETCHTYPEB_BYTES);
+        memset(buf, 0, bufsize);
+    }
+   
+    return etch_flexbuf_create_bi (buf, bufsize, datalen, index);
+}
+
+
+/**
+ * etch_flexbuf_create_b()
+ * create a flex buffer out of an existing buffer, ready to read to, 
+ * using specified size and an index of zero.
+ *
+ * @param buf the existing buffer.
+ * @param bufsize the buffer size.
+ * @param datalen the data length in the buffer
+ *
+ * @return the created and initialized the flex buffer.
+ *
+ */
+etch_flexbuffer *etch_flexbuf_create_b (void *buf, size_t bufsize, size_t datalen)
+{
+    return etch_flexbuf_create_bi(buf, bufsize, datalen, 0);
+}
+
+
+/**
+ * etch_flexbuf_create_bi()
+ * create a flex buffer out of an existing buffer, ready to read with specified 
+ * index and size.
+ * @param buf the existing buffer.
+ * @param bufsize the buffer size.
+ * @param datalen the data length in the buffer
+ * @param index current position of the buffer.
+ */
+etch_flexbuffer *etch_flexbuf_create_bi (void *buf, size_t bufsize, size_t datalen, size_t index)
+{
+    etch_flexbuffer *fbuf = (etch_flexbuffer*) new_object
+        (sizeof(etch_flexbuffer), ETCHTYPEB_FLEXBUF, CLASSID_FLEXBUF);
+
+    fbuf->destroy = destroy_etch_flexbuffer;
+
+    fbuf->buf     = buf;
+    fbuf->bufsize = bufsize;
+    fbuf->datalen = datalen;
+    fbuf->index   = index;
+    fbuf->is_littleendian = IS_ETCH_TRANSPORT_LITTLEENDIAN;
+    return fbuf;    
+}
+
+
+/**
+ * etch_flexbuf_get_buffer()
+ * @return the current byte array. might change if any operation
+ * needs to extend length past the end of the array.
+ */
+byte* etch_flexbuf_get_buffer (etch_flexbuffer *fbuf)
+{
+	return fbuf->buf;
+}
+
+
+/**
+ * etch_flexbuf_clear()
+ * zero fill the internal buffer
+ */
+void etch_flexbuf_clear (etch_flexbuffer *fbuf)
+{
+	memset (fbuf->buf, 0, fbuf->bufsize);
+}
+
+
+/**
+ * etch_flexbuf_ensure_size().
+ * verify sufficient buffer capacity, reallocating if necessary.
+ * @return boolean value indicating if buffer is as requested.
+ */
+static int etch_flexbuf_ensure_size (etch_flexbuffer *fbuf, size_t reqsize)
+{
+    byte *newbuf = NULL;
+    size_t newsize = fbuf->bufsize;
+	if (reqsize  < ETCH_INIT_FLEXBUFSIZE)
+		reqsize  = ETCH_INIT_FLEXBUFSIZE;
+	if (reqsize <= newsize) return TRUE;	
+    if (reqsize  > ETCH_MAX_FLEXBUFSIZE) return FALSE;
+	
+	while(reqsize > newsize) newsize += ETCH_INIT_FLEXBUFSIZE;
+	newbuf = etch_realloc (fbuf->buf, newsize, 0);
+    fbuf->buf = newbuf;
+    fbuf->bufsize = newsize; 
+    return TRUE;
+}
+
+
+/**
+ * destroy_etch_flexbuffer()
+ * etch_flexbuffer destructor
+ */
+int destroy_etch_flexbuffer(etch_flexbuffer *fbuf)
+{
+    if (fbuf == NULL) return 0; 
+    if (fbuf->refcount > 0 && --fbuf->refcount > 0) return 0; 
+
+    if (!is_etchobj_static_content(fbuf))
+        etch_free(fbuf->buf);  /* OK if null */
+
+    destroy_objectex((objmask*) fbuf);
+    return 0;
+}
+
+
+/**
+ * sets a new data length. If the index is larger than new length, 
+ * the index is set to the new length as well. 
+ * the method name was retained from java, however it is more properly 
+ * set_data_length, since as noted previously, "length" is ambiguous,
+ * referring to data length, not to allocated bytes. 
+ */
+int etch_flexbuf_set_length (etch_flexbuffer *fbuf, size_t new_datalen)
+{
+    int result = 0;
+
+    if (new_datalen >= 0 && etch_flexbuf_ensure_size(fbuf, new_datalen))
+    {   
+        fbuf->datalen = new_datalen;  
+
+        if (fbuf->index > new_datalen)
+            fbuf->index = new_datalen;
+    }
+    else result = -1;
+
+   return result;
+}
+
+
+/**
+ * sets a new buffer index. the index must be greater than 0 and less
+ * than the buffer size
+ * @param fbuf the buffer pointer to be set.
+ * @param index the new index for the buffer.
+ */
+int etch_flexbuf_set_index (etch_flexbuffer *fbuf, size_t index)
+{
+    if (index < 0 || index > fbuf->datalen) return -1;
+    fbuf->index = index;
+    return 0;
+}
+
+
+/**
+ * get the number of bytes available in the buffer.
+ * @return the available space in the buffer.
+ */
+size_t etch_flexbuf_avail (etch_flexbuffer *fbuf)
+{
+    return (fbuf->datalen - fbuf->index);
+}
+
+
+/**
+ * etch_flexbuffer_reset_to()
+ * set index to zero and length to specified length.
+ */
+int etch_flexbuffer_reset_to (etch_flexbuffer *fbuf, size_t new_datalen)
+{
+    const int result = etch_flexbuf_set_length (fbuf, new_datalen);
+    fbuf->index = 0;
+    return result;
+}
+
+
+/**
+ * etch_flexbuf_reset()
+ * set index and length to zero, same as etch_flexbuf_set_index(buf, 0)
+ */
+etch_flexbuffer *etch_flexbuf_reset (etch_flexbuffer *fbuf)
+{
+    fbuf->index = fbuf->datalen = 0;
+	return fbuf;
+}
+
+
+/**
+ * Compacts the buffer by moving remaining data (from index to length)
+ * to the front of the buffer. Sets index to 0, and sets length to
+ * avail (before index was changed).
+ * @return this flex buffer object.
+ */
+etch_flexbuffer *etch_flexbuf_compact(etch_flexbuffer *fbuf)
+{
+    size_t curlen;
+	if (fbuf->index == 0) return fbuf;
+	
+	if (0 == (curlen = etch_flexbuf_avail(fbuf)))
+	{
+		etch_flexbuf_set_length(fbuf, 0);
+		return fbuf;
+	}
+	
+    memmove(fbuf->buf, fbuf->buf+fbuf->index, curlen);
+	fbuf->index = 0;
+	fbuf->datalen = curlen;
+	
+	return fbuf;
+}
+
+
+/**
+ * Copies data from the internal buffer to buf.
+ *
+ * @param fbuf the flex buffer to get data from.
+ * @param buf a buffer to receive the data. At most
+ * min( len, avail() ) bytes are transferred, starting
+ * at off.
+ * @param off the index in buf to receive the data.
+ * Off must be >= 0 && <= buf.datalen.
+ * @param len the max amount of data to transfer. Len
+ * must be >= 0 and <= buf.datalen - off.
+ * @return the amount of data transferred.
+ */
+size_t etch_flexbuf_get(etch_flexbuffer *fbuf, byte *buf, size_t off, size_t len)
+{
+    size_t bytecount = 0, avail = etch_flexbuf_avail(fbuf);
+	if (len <= 0 || NULL == buf) return 0;
+
+    bytecount = min(len, avail);	
+                     /* changed 6/16 to add index */
+    memcpy(buf + off, fbuf->buf + fbuf->index + off, bytecount);
+	fbuf->index += bytecount;
+	
+	return bytecount;
+}
+
+
+/**
+ * etch_flexbuf_get_allfrom()
+ * return buffer contents starting at index, in a byte vector, caller owns returned memory
+ */
+byte* etch_flexbuf_get_allfrom(etch_flexbuffer* fbuf, size_t index, size_t* out_count)
+{
+    byte* newbuf = 0;
+    size_t bytecount = 0;
+    if (index < 0) index = fbuf->index;
+    if (index > fbuf->datalen) index = fbuf->datalen;
+    fbuf->index = index;  /* 6/16 so etch_flexbuf_get can skip index */
+
+    bytecount = fbuf->datalen - index;  
+    newbuf    = etch_malloc(bytecount, ETCHTYPEB_BYTES);
+
+    bytecount = etch_flexbuf_get(fbuf, newbuf, 0, bytecount);
+
+    if (out_count) *out_count = bytecount; 
+    return newbuf;
+}
+
+
+/**
+ * etch_flexbuf_get_all()
+ * return buffer contents in a byte array, caller owns memory
+ */
+byte* etch_flexbuf_get_all(etch_flexbuffer* fbuf, size_t* out_count)
+{
+    return etch_flexbuf_get_allfrom(fbuf, fbuf->index, out_count); 
+}
+
+
+/**
+ * return next byte in buffer
+ */
+int etch_flexbuf_get_byte(etch_flexbuffer *fbuf, byte* out)
+{
+   if (etch_flexbuf_avail(fbuf) < sizeof(byte)) return -1;  
+   *out = fbuf->buf[fbuf->index++];
+   return 0;
+}
+
+
+void reverse2(unsigned short* item)
+{
+    unsigned short newitem = 0;
+    byte *p = (byte*) &item, *q = (byte*) &newitem;
+    p[0] = q[1]; p[1] = q[0]; 
+    *item = newitem; 
+}
+
+void reverse4(unsigned* item)
+{
+    unsigned curitem = *item, newitem = 0;
+    byte *p = (byte*) &curitem, *q = (byte*) &newitem;
+    q[0] = p[3]; q[1] = p[2]; q[2] = p[1]; q[3] = p[0];
+    *item = newitem; 
+}
+
+
+/**
+ * etch_flexbuf_get_short()
+ * @return a short composed from the next 2 bytes.
+ */
+int etch_flexbuf_get_short(etch_flexbuffer *fbuf, short* out)
+{   
+    int value, svalue;
+    if (etch_flexbuf_avail(fbuf) < sizeof(short)) return -1;
+
+	if (fbuf->is_littleendian)
+	{
+		value = fbuf->buf[fbuf->index++] & 255;
+		svalue = (short) (value + ((fbuf->buf[fbuf->index++] & 255) << 8));
+	}
+	else
+    {   value  = fbuf->buf[fbuf->index++]; /* big endian */
+	    svalue = (short) ((value << 8) + (fbuf->buf[fbuf->index++] & 255));
+    }
+
+    *out = svalue;
+    return 0;
+}
+
+
+/**
+ * etch_flexbuf_get_int()
+ * @return an int composed from the next 4 bytes.
+ * TODO convert the rest of these functions to not do byte by byte subscripting
+ */
+int etch_flexbuf_get_int(etch_flexbuffer *fbuf, int* out)
+{
+    int value = 0, bytesavail = (int) etch_flexbuf_avail(fbuf);
+    if (bytesavail < sizeof(int)) return -1;
+
+    value = *( (int*) &fbuf->buf[fbuf->index] ); 
+
+	if (! fbuf->is_littleendian);	
+        reverse4(&value);
+
+    fbuf->index += sizeof(int);
+    *out = value;
+    return 0;
+}
+
+
+#if(0)
+/**
+ * @return an int composed from the next 4 bytes.
+ * @throws IOException if avail() < 4.
+ */
+int etch_flexbuf_get_int(etch_flexbuffer *fbuf)
+{
+  int value = 0;
+	if (fbuf->is_littleendian)
+	{
+		// little-endian
+		value = fbuf->buf[fbuf->index++] & 255;
+		value += ((fbuf->buf[fbuf->index++] & 255) << 8);
+		value += ((fbuf->buf[fbuf->index++] & 255) << 16);
+		return value + ((fbuf->buf[fbuf->index++] & 255) << 24);
+	}
+	
+	// big-endian
+	value = fbuf->buf[fbuf->index++];
+	value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	return  (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+}
+#endif
+
+
+/**
+ * etch_flexbuf_get_long()
+ * @return a long composed from the next 8 bytes.
+ * note jim are we taking sign into consideration on reversal?
+ */
+int etch_flexbuf_get_long(etch_flexbuffer *fbuf, int64* out)
+{
+    int64 value, valout;
+    int bytesavail = (int) etch_flexbuf_avail(fbuf);
+    if (bytesavail < sizeof(int64)) return -1;
+
+	if (fbuf->is_littleendian)
+	{
+		/* little-endian */
+		value = fbuf->buf[fbuf->index++] & 255;
+		value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 8);
+		value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 16);
+		value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 24);
+		value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 32);
+		value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 40);
+		value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 48);
+		valout = value + (((int64)(fbuf->buf[fbuf->index++] & 255)) << 56);
+	}
+    else /* big-endian */
+    {   value = fbuf->buf[fbuf->index++];
+	    value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	    value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	    value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	    value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	    value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	    value = (value << 8) + (fbuf->buf[fbuf->index++] & 255);
+	    valout =(value << 8) + (fbuf->buf[fbuf->index++] & 255);
+    }
+
+    *out = valout;
+    return 0;
+}
+
+
+/**
+ * etch_flexbuf_get_float()
+ * @return a float from the next available bytes.
+ */
+int etch_flexbuf_get_float(etch_flexbuffer *fbuf, float* out)
+{
+    float value;
+    if (-1 == etch_flexbuf_get_int(fbuf, (int*) &value)) return -1;
+    *out = value;
+    return 0;
+}
+
+
+/**
+ * etch_flexbuf_get_double()
+ * @return a double from the next available bytes.
+ */
+int etch_flexbuf_get_double(etch_flexbuffer *fbuf, double* out)
+{
+    double value;
+    if (-1 == etch_flexbuf_get_long(fbuf, (int64*) &value)) return -1;
+    *out = value;
+    return 0;
+}
+
+
+
+/**
+ * fills a buffer fully from the next available bytes.
+ * @param b
+ * @throws IOException if avail() < b.datalen.
+ */
+size_t etch_flexbuf_get_fully( etch_flexbuffer *fbuf, byte *b, size_t bufsize )
+{
+    return etch_flexbuf_get( fbuf, b, 0, bufsize );
+}
+
+
+/**
+ * If index has moved past length during a put, then adjust length
+ * to track index.
+ */
+static void etch_flexbuf_fix_length(etch_flexbuffer *fbuf)
+{
+	if (fbuf->index > fbuf->datalen)
+		fbuf->datalen = fbuf->index;
+}
+
+
+/**
+ * Puts some bytes into the buffer as if by repeated calls to put().
+ * @param buf the source of the bytes to put.
+ * @param off the index to the first byte to put.
+ * @param bytecount the number of bytes to put.
+ * @return count of bytes put
+ */
+size_t etch_flexbuf_put (etch_flexbuffer *fbuf, byte *buf, size_t off, size_t bytecount)
+{
+	if (bytecount <= 0) return 0;	
+	if (!etch_flexbuf_ensure_size (fbuf, fbuf->index + bytecount)) return 0;
+
+    memcpy(fbuf->buf + fbuf->index, buf + off, bytecount);
+	fbuf->index += bytecount;
+	etch_flexbuf_fix_length (fbuf);	
+	return bytecount;
+}
+
+
+/**
+ * Copies the specified number of bytes from buf[index] into buffer
+ * as if by repeated execution of put( buf.get() ).
+ * @param buf the source of the bytes to put.
+ * @param len the number of bytes to put. if -1, copy everything.  
+ * @return number of bytes put
+ */
+size_t etch_flexbuf_put_from(etch_flexbuffer *dstfb, etch_flexbuffer *srcfb, size_t bytecount)
+{
+    size_t bytes_put = 0;
+    if (bytecount == -1) 
+        bytecount = srcfb->datalen - srcfb->index;
+
+	bytes_put = etch_flexbuf_put (dstfb, srcfb->buf, srcfb->index, bytecount);
+
+	etch_flexbuf_skip (srcfb, bytes_put, FALSE);
+
+	return bytes_put;
+}
+
+
+/**
+ * etch_flexbuf_put_byte()
+ * @return number of bytes put
+ */
+size_t etch_flexbuf_put_byte (etch_flexbuffer *fbuf, byte value)
+{
+    size_t bytes_put = 0;
+
+	if (etch_flexbuf_ensure_size(fbuf, fbuf->index + 1))
+    {
+        fbuf->buf[fbuf->index++] = value;
+    	etch_flexbuf_fix_length(fbuf);
+        bytes_put = sizeof(value);
+    }
+
+    return bytes_put;
+}
+
+
+/**
+ * etch_flexbuf_put_short()
+ */
+size_t etch_flexbuf_put_short(etch_flexbuffer *fbuf, short value)
+{
+    if (!etch_flexbuf_ensure_size( fbuf, fbuf->index + sizeof(value) ))
+        return 0;
+
+	if (fbuf->is_littleendian)
+	{
+		fbuf->buf[fbuf->index++] = (byte) value;
+		fbuf->buf[fbuf->index++] = (byte) (value >> 8);
+	}
+	else
+	{
+		fbuf->buf[fbuf->index++] = (byte) (((unsigned short)value) >> 8);
+		fbuf->buf[fbuf->index++] = (byte) value;
+	}
+	
+	etch_flexbuf_fix_length(fbuf);
+
+    return sizeof(value);
+}
+
+
+/**
+ * etch_flexbuf_put_int()
+ */
+size_t etch_flexbuf_put_int( etch_flexbuffer *fbuf, int value )
+{
+    if (!etch_flexbuf_ensure_size( fbuf, fbuf->index + sizeof(value) ))
+        return 0;
+
+    if (fbuf->is_littleendian)
+	{
+		fbuf->buf[fbuf->index++] = (byte) value;
+		fbuf->buf[fbuf->index++] = (byte) (value >> 8);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 16);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 24);
+	}
+	else
+	{
+		fbuf->buf[fbuf->index++] = (byte) ( ((unsigned int) value) >> 24);
+		fbuf->buf[fbuf->index++] = (byte) ( ((unsigned int) value) >> 16);
+		fbuf->buf[fbuf->index++] = (byte) ( ((unsigned int) value) >> 8);
+		fbuf->buf[fbuf->index++] = (byte) value;
+	}
+	
+	etch_flexbuf_fix_length(fbuf);
+
+    return sizeof(value);
+}
+
+
+/**
+ * etch_flexbuf_put_long()
+ */
+size_t etch_flexbuf_put_long(etch_flexbuffer *fbuf, int64 value )
+{
+    if (!etch_flexbuf_ensure_size( fbuf, fbuf->index + sizeof(value) ))
+        return 0;
+
+	if (fbuf->is_littleendian)
+	{
+		fbuf->buf[fbuf->index++] = (byte) value;
+		fbuf->buf[fbuf->index++] = (byte) (value >> 8);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 16);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 24);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 32);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 40);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 48);
+		fbuf->buf[fbuf->index++] = (byte) (value >> 56);
+	}
+	else
+	{
+		fbuf->buf[fbuf->index++] = (byte) ( ((uint64) value ) >> 56);
+		fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 48);
+		fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 40);
+		fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 32);
+		fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 24);
+		fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 16);
+		fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 8);
+		fbuf->buf[fbuf->index++] = (byte) value;
+	}
+	
+	etch_flexbuf_fix_length(fbuf);
+
+    return sizeof(value);
+}
+
+
+/**
+ * etch_flexbuf_put_float()
+ */
+size_t etch_flexbuf_put_float( etch_flexbuffer *fbuf, float value )
+{
+	/* return etch_flexbuf_put_int( fbuf, * ((int *)( &value )) ); */
+    const unsigned int u = * ( (int*)&value );
+    return etch_flexbuf_put_int(fbuf, u); 
+}
+
+
+/**
+ * etch_flexbuf_put_double()
+ */
+size_t etch_flexbuf_put_double(etch_flexbuffer *fbuf, double value )
+{
+	/* return etch_flexbuf_put_long( fbuf, *( (int64*) &value ) ); */
+    const int64 u = * ( (int64*)&value );
+    return etch_flexbuf_put_long(fbuf, u);
+}
+
+
+/**
+ * Adjusts index as if by a get or put but without transferring
+ * any data. This could be used to skip over a data item in an
+ * input or output buffer.
+ * 
+ * @param len the number of bytes to skip over. Len must be
+ * >= 0. If put is false, it is an error if len > avail().
+ * If put is true, the buffer may be extended (and the buffer
+ * length adjusted).
+ * 
+ * @param put if true it is ok to extend the length of the
+ * buffer.
+ * 
+ * @return this flex buffer object.
+ * 
+ * @throws EOFException if put is false and len > avail().
+ * 
+ * @throws IOException if the max buffer size is exceeded.
+ */
+etch_flexbuffer *etch_flexbuf_skip(etch_flexbuffer *fbuf, size_t len, int put )
+{
+	if (len  < 0) return NULL;	
+	if (len == 0) return fbuf;
+	
+	if (put)
+	{
+		etch_flexbuf_ensure_size( fbuf, fbuf->index+len );
+		fbuf->index += len;
+		etch_flexbuf_fix_length(fbuf);
+		return fbuf;
+	}
+	
+	fbuf->index += len;	
+	return fbuf;
+}