blob: 367cb718697efcdfc5c13568c347304b297201a9 [file]
/* $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_serializer.c
*/
#include "etch_serializer.h"
#include "etch_defvalufact.h"
#include "etch_arrayval.h"
#include "etch_encoding.h"
#include "etch_syncobj.h"
#include "etch_global.h"
#include "etchexcp.h"
#include "etchmap.h"
#include "etchlog.h"
char* ETCHIMPX = "IMPX";
objmask* etchserializer_defexportval (etch_serializer* thisx, objmask* objval);
objmask* etchserializer_defimportval (etch_serializer* thisx, objmask* structval);
int destroy_etch_serializer(etch_serializer* thisx);
/* - - - - - - - - - - - - - - - - - -
* constructors/destructors
* - - - - - - - - - - - - - - - - - -
*/
/**
* new_etch_serializer()
* etch_serializer constructor
*/
etch_serializer* new_etch_serializer(const int objsize)
{
const int size = objsize? objsize: sizeof(etch_serializer);
etch_serializer* newobj = (etch_serializer*) new_object
(sizeof(etch_serializer), ETCHTYPEB_SERIALIZER, CLASSID_NONE);
newobj->destroy = destroy_etch_serializer;
newobj->import_value = etchserializer_defimportval;
newobj->export_value = etchserializer_defexportval;
return newobj;
}
/**
* destroy_etch_serializer()
* etch_serializer destructor
*/
int destroy_etch_serializer(etch_serializer* thisx)
{
if (thisx->refcount > 0 && --thisx->refcount > 0) return -1;
if (!is_etchobj_static_content(thisx))
{
if (thisx->impl)
{ thisx->impl->destroy(thisx->impl);
thisx->impl = NULL;
}
}
return destroy_objectex((objmask*) thisx);
}
/**
* etch_serializer_init()
* generic static intitializer for import export helper serializers.
* caller retains ownership of *all* parameters to this method.
* @param obj_type type of the object being serialized
* @param keyname name of an existing etch_field which will key the import
* and export object in its serialization map.
* @param obj_class numeric etch object type and class id of the object
being serialized.
* @param c2tmap a vf's map of numeric class to object type associations.
* @param vtor the validator object used to vet objects of this type.
* @param new_szr a pointer to the constructor for serializers of the
* specified type.
*/
int etch_serializer_init(etch_type* obj_type, const wchar_t* keyname,
const unsigned obj_class, etch_hashtable* c2tmap, etch_validator* vtor,
etch_serializer_ctor new_szr)
{
etch_serializer* newimpexhelper = NULL;
/* serializer instantiation is awkward, since we are installing serializers
* to singleton types, but the class to type map is not singleton.
* investigate, and if reasonable, move the c2t maintenance to a higher
* level, and invoke this code only once per type instantiation.
* unfortunately a type does not indicate its correpsonding class,
* i.e. we know a type is "foo", but the type does not know it maps to
* ETCHTYPE_FOO, CLASSID_FOO. so here, the serializers, in their ctors,
* determine that mapping, and pass that class here. ideally we can eliminate
* both the c2t and class parameters from the serializer initialization.
*/
/* get reference to field key having specified name, not owned here */
etch_field* szr_key = etchtype_get_field_by_name (obj_type, keyname);
if (NULL == szr_key) return -1;
/* map this class identifier to associated type object */
class_to_type_map_put(c2tmap, obj_class, obj_type);
/* if the type's serializer is already instantiated, we don't want
* to do so again. this is the awkardness commented above. */
if (etchtype_get_component_type(obj_type)) return 0;
/* set component type for arrays of specified class */
etchtype_set_component_type(obj_type, obj_class);
/* instantiate the new import/export helper */
newimpexhelper = new_szr(obj_type, szr_key);
/* attach, and assign ownership of, the new helper object to the type */
etchtype_set_impexphelper(obj_type, newimpexhelper);
return NULL == vtor? 0: /* attach the supplied validator to the type */
etchtype_put_validator(obj_type, clone_field(szr_key), (objmask*) vtor);
}
/* - - - - - - - - - - - - - - - - - -
* exception serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_exception_export_value()
* export value for any exception
* @param objval an etch_exception object. caller owns it,
* and presumably will destroy it upon return from this method.
* @return the exported disposable structvalue object. caller must cast it.
*/
objmask* etchserializer_exception_export_value (etch_serializer* thisx, objmask* objval)
{
int result = 0;
char* excpvalue = NULL;
const int THISINITSIZE = 2;
etch_string* stringobj = NULL;
etch_structvalue* structval = NULL;
etch_exception* excpobj = (etch_exception*) objval;
if (!is_etch_exception(excpobj))
{ etchlog(ETCHIMPX, ETCHLOG_ERROR, "value is not exception\n");
return NULL;
}
/* we tostring() the exception, getting back a buffer which we own here.
* we pass ownership of that buffer to an etch_string, and then pass
* ownership of that etch_string to the returned structvalue. recall that
* a structvalue owns all its content memory, and assumes its keys and
* values are etch objects on which it will invoke destructors when it
* itself is destroyed. we clone a type key for a similar reason.
*/
excpvalue = excp_tostringx(excpobj->value);
stringobj = new_string_from(excpvalue, ETCH_ENCODING_ASCII);
structval = new_structvalue((etch_type*) thisx->type, THISINITSIZE);
result = structvalue_put(structval, clone_field(thisx->field), (objmask*)stringobj);
return (objmask*) structval;
}
/**
* etchserializer_exception_import_value()
* import value for any exception.
* @param objval an etch_structvalue of appropriate type for the exception.
* caller retains ownership of this object as with all imports.
* @return an opaque etch object containing the imported exception.
*
* caller owns and must destroy the returned object.
* use: etch_exception* x = get_exception(returnedobj);
* to point into and inspect the exception.
*/
objmask* etchserializer_exception_import_value
(etch_serializer* thisx, objmask* objval, excptype xtype)
{
wchar_t* unistring = NULL;
etch_string* impstring = NULL;
etch_exception* exception = NULL;
etch_structvalue* structval = (etch_structvalue*) objval;
if (!is_etch_struct(structval)) return NULL;
if (!structvalue_is_type(structval, thisx->type)) return NULL;
/* fetch the exception string out of the struct. not owned here. */
impstring = (etch_string*) structvalue_get (structval, thisx->field);
if (!is_etch_string(impstring)) return NULL;
if (IS_ETCH_ENCODING_8BIT(impstring->encoding))
/* recall that we carry all non-internal strings as unicode.
* we own the returned unicode buffer for the moment. */
etch_ansi_to_unicode (&unistring, impstring->v.valc);
else /* todo figure a way to not re-allocate the string */
unistring = new_wchar (impstring->v.valw);
/* create an exception object from the deserialized string. this object
* manages the exception memory according to flags supplied it. we set
* such a flag here, ETCHEXCP_FREETEXT, indicating that the exception
* owns the text buffer we give it. thus we no longer own unistring */
exception = new_etch_exception (xtype, unistring, ETCHEXCP_FREETEXT);
return (objmask*) exception;
}
/**
* etchserializer_excp_import_value()
* virtual import value for runtime exception.
* @param objval an etch_structvalue of type etch runtime exception.
* caller retains ownership of this object as with all imports.
* @return an opaque etch object containing the imported exception.
*
* caller owns and must destroy the returned object.
* use: etch_exception* x = get_exception(returnedobj);
* to point into and inspect the exception.
*/
objmask* etchserializer_excp_import_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_exception_import_value(thisx, objval, EXCPTYPE_GENERIC);
}
/**
* new_exception_serializer()
* etch_serializer_excp constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_exception_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_EXCP;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_exception_export_value;
newobj->import_value = etchserializer_excp_import_value;
return newobj;
}
/**
* etch_serializer_exception_init()
* static intitializer for runtime exception serializer.
* creates the impexp serializer and installs it to the supplied type.
* @param thistype type of the serializer (runtime exception)
*/
int etch_serializer_exception_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* keyname = str_msg; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_EXCEPTION, CLASSID_EXCEPTION);
return etch_serializer_init(thistype, keyname, thisclass, c2tmap,
etchvtor_string_get(0), new_exception_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* runtime exception serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_rtxcp_export_value()
* virtual export value for runtime exception
* @param objval a, etchexception blob, caller owns it and presumably will
* destroy it upon return from this method.
* @return the exported disposable structvalue object. caller must cast it.
*/
objmask* etchserializer_rtxcp_export_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_exception_export_value(thisx, objval);
}
/**
* etchserializer_rtxcp_import_value()
* virtual import value for runtime exception.
* @param objval an etch_structvalue of type etch runtime exception.
* caller retains ownership of this object as with all imports.
* @return an opaque etch object containing the imported exception.
*
* caller owns and must destroy the returned object.
* use: etch_exception* x = get_exception(returnedobj);
* to point into and inspect the exception.
*/
objmask* etchserializer_rtxcp_import_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_exception_import_value(thisx, objval, EXCPTYPE_ETCHRUNTIME);
}
/**
* new_runtime_exception_serializer()
* etch_serializer_rtxcp constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_runtime_exception_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_RTXCP;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_rtxcp_export_value;
newobj->import_value = etchserializer_rtxcp_import_value;
return newobj;
}
/**
* etch_serializer_rtxcp_init()
* static intitializer for runtime exception serializer.
* creates the impexp serializer and installs it to the supplied type.
* @param thistype type of the serializer (runtime exception)
*/
int etch_serializer_rtxcp_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* keyname = str_msg; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_EXCEPTION, CLASSID_RUNTIME_EXCEPTION);
return etch_serializer_init(thistype, keyname, thisclass, c2tmap,
etchvtor_string_get(0), new_runtime_exception_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* auth exception serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_authxcp_export_value()
* virtual export value for auth exception
* @param objval a, etchexception blob, caller owns it and presumably will
* destroy it upon return from this method.
* @return the exported disposable structvalue object. caller must cast it.
*/
objmask* etchserializer_authxcp_export_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_exception_export_value(thisx, objval);
}
/**
* etchserializer_authxcp_import_value()
* virtual import value for runtime exception.
* @param objval an etch_structvalue of type etch runtime exception.
* caller retains ownership of this object as with all imports.
* @return a nonspecific etch object containing the imported exception.
*
* caller owns and must destroy the returned object.
* use: etch_exception* x = get_exception(returnedobj);
* to point into and inspect the exception.
*/
objmask* etchserializer_authxcp_import_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_exception_import_value(thisx, objval, EXCPTYPE_ETCHAUTH);
}
/**
* new_auth_exception_serializer()
* etch_serializer_auth exception constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_auth_exception_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_AUTHXCP;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_authxcp_export_value;
newobj->import_value = etchserializer_authxcp_import_value;
return newobj;
}
/**
* etch_serializer_authxcp_init()
* static intitializer for auth exception serializer.
* creates the impexp serializer and installs it to the supplied type.
* @param thistype type of the serializer (runtime exception)
*/
int etch_serializer_authxcp_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* keyname = str_msg; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_EXCEPTION, CLASSID_AUTH_EXCEPTION);
return etch_serializer_init(thistype, keyname, thisclass, c2tmap,
etchvtor_string_get(0), new_auth_exception_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* list serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_list_export_value()
* virtual export value for list
* @param objval an etch_arraylist containing values to export to tdo.
* caller retains ownership of this object; this method however sets the readonly
* mark on this object, such that it will not destroy its content, which was
* assigned to the arraylist wrapped in the returned struct.
* the c binding internally models a list type as an etch_arraylist.
* @return the exported structvalue object, containing an etch_arraylist.
* since we can't pass around raw arrays as does the java binding in this case,
* this serializer chooses to use an arraylist as the export object type for lists.
* while it may seem convoluted that the exported from and exported to objects are
* the same object type (not the same object however), the reason is the vf export
* interface contract, i.e. caller relinquishes memory for the export from object,
* and acquires memory for the export to objects.
*/
objmask* etchserializer_list_export_value(etch_serializer* thisx, objmask* objval)
{
int result = 0;
const int THISINITSIZE = 2;
etch_arraylist* listobj = NULL;
etch_arraylist* listnew = NULL;
etch_structvalue* outstruct = NULL;
if (!is_etch_arraylist(objval)) return NULL;
/* copy caller's list's content to a new list */
listobj = (etch_arraylist*) objval;
listnew = new_synchronized_arraylist_from(listobj);
/* value factory export_custom_value() will destroy() the export from object;
* we mark that object such that its content will not be destroyed with it */
listobj->is_readonly = TRUE;
/* assign ownership of the new list to the returned struct */
outstruct = new_structvalue((etch_type*) thisx->type, THISINITSIZE);
result = structvalue_put(outstruct, clone_field(thisx->field), (objmask*) listnew);
return (objmask*) outstruct; /* caller owns this structvalue */
}
/**
* etchserializer_list_import_value()
* virtual import value for etch list.
* @param objval an etch_structvalue of type etch list.
* caller retains ownership of this object as with all imports.
* @return a *disposable* etch_arraylist containing the imported data objects.
*
* note that the c binding works a bit differently that does the java here.
* java tdi populates the structvalue with an object[]. in c the tdi inserts a
* synchronized etch_arraylist to the structvalue.
*/
objmask* etchserializer_list_import_value(etch_serializer* thisx, objmask* objval)
{
etch_arraylist *inarray = NULL, *outarray = NULL;
etch_structvalue* instruct = (etch_structvalue*) objval;
if (!is_etch_struct(instruct)) return NULL;
if (!structvalue_is_type(instruct, thisx->type)) return NULL;
/* fetch the arrayvalue from the struct. struct owns it. */
inarray = (etch_arraylist*) structvalue_get(instruct, thisx->field);
if (!is_etch_arraylist(inarray)) return NULL;
/* copy content to return list */
outarray = new_synchronized_arraylist_from(inarray);
/* value factory import_custom_value() will destroy() the import struct
* which will call destructors on its content. we mark the import list
* object such that its content will not be destroyed with it, since
* we just copied that content to the return list */
set_etchobj_static_content(inarray);
return (objmask*) outarray; /* caller owns the returned list */
}
/**
* new_list_serializer()
* etch_serializer_list constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_list_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_LIST;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_list_export_value;
newobj->import_value = etchserializer_list_import_value;
return newobj;
}
/**
* etch_serializer_list_init()
* static intitializer for list serializer.
* creates the list impex serializer and installs it to the supplied type.
* @param thistype type of the serializer (list)
*/
int etch_serializer_list_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* key_name = str_values; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_ETCHLIST, CLASSID_ETCH_LIST);
return etch_serializer_init(thistype, key_name, thisclass, c2tmap,
etchvtor_object_get(1), new_list_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* map serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_map_export_value()
* virtual export value for etch map
* @param objval an etch_hashtable containing values to export. caller owns it,
* and presumably will destroy it on return from this method. this method marks
* this object such that its destructor will not destroy its content objects,
* ownership of which is transferred here to the returned arraylist.
* @return the exported structvalue object in which the lone entry is an
* etch_arraylist containing the map keys and values as consecutive entries.
* caller owns this returned structvalue.
*/
objmask* etchserializer_map_export_value(etch_serializer* thisx, objmask* objval)
{
int result = 0, mapsize = 0, listsize = 0, is_expected_maptype = 0;
etch_iterator iterator;
const int THISINITSIZE = 2;
const int is_this_a_set = (thisx->type->id == builtins._mt__etch_set->id);
etch_hashtable* impmap = NULL;
etch_arraylist* explist = NULL;
etch_structvalue* expstruct = NULL;
if (!is_etch_hashtable(objval)) return NULL;
impmap = (etch_hashtable*) objval;
mapsize = etchmap_count(impmap);
listsize = is_this_a_set? mapsize: mapsize * 2;
/* the underlying hashtable for an etch map must be explicitly marked
* as having object-key, object-value content, since the export list
* content is object-key, object-value, object-key, object value, etc. */
is_expected_maptype = is_this_a_set?
impmap->content_type == ETCHHASHTABLE_CONTENT_OBJECT_NONE:
impmap->content_type == ETCHHASHTABLE_CONTENT_OBJECT_OBJECT;
if (!is_expected_maptype) return NULL;
/* create native array for export, marked such that
* destructors will be called on list content */
explist = new_synchronized_arraylist(listsize, 0);
explist->class_id = CLASSID_ETCH_ARRAYLIST;
explist->content_type = ETCHARRAYLIST_CONTENT_OBJECT;
explist->is_readonly = FALSE;
explist->content_obj_type = impmap->content_obj_type;
explist->content_class_id = impmap->content_class_id;
set_iterator(&iterator, impmap, &impmap->iterable);
while(iterator.has_next(&iterator)) /* copy map data to array */
{
arraylist_add(explist, iterator.current_key);
if (is_this_a_set); /* a set has only keys */
else arraylist_add(explist, iterator.current_value);
iterator.next(&iterator);
}
/* mark caller's map such that it will not destroy its content,
* ownership of which we just transferred to the export array */
impmap->is_readonly_keys = impmap->is_readonly_values = TRUE;
impmap->freehook = etch_noop_clear_handler;
expstruct = new_structvalue((etch_type*) thisx->type, THISINITSIZE);
/* here we assign ownership of the new arraylist to the struct */
result = structvalue_put(expstruct, clone_field(thisx->field), (objmask*)explist);
return (objmask*) expstruct; /* caller owns this structvalue */
}
/**
* etchserializer_map_import_value()
* virtual import value for etch map.
* @param objval an etch_structvalue of type etch map, wrapping a
* single entry of etch_arrayvalue, wrapping an etch_arraylist in which
* consecutive entries represent a map key and a map value. this method
* will mark the arraylist such that it will not destroy its object content.
* caller retains ownership of this object as with all imports.
* @return a disposable etch_hashtable containing the imported data objects.
* caller must cast it and destroy it.
*
* note that the c binding works a bit differently that does the java here.
* java tdi populates the structvalue with an object[]. in c the tdi inserts a
* synchronized etch_arraylist wrapped by an etch_arrayvalue, to the structvalue.
*/
objmask* etchserializer_map_import_value(etch_serializer* thisx, objmask* objval)
{
int i = 0, result = 0, listcount = 0, mapsize = 0;
etch_hashtable* expmap = NULL;
etch_arraylist* implist = NULL;
etch_structvalue* impstruct = NULL;
const int is_this_a_set = thisx->type->id == builtins._mt__etch_set->id;
if (!is_etch_struct(objval)) return NULL;
impstruct = (etch_structvalue*) objval;
if (!structvalue_is_type(impstruct, thisx->type)) return NULL;
/* get the synchronized arraylist out of the struct and mark the list
* such that it no longer owns its object content, ownership of which we
* are transferring to the exported map.
*/
implist = (etch_arraylist*) structvalue_get(impstruct, thisx->field);
if (!is_etch_arraylist(implist)) return NULL;
set_etchobj_static_content(implist);
listcount = implist->count;
/* instantiate a map configured appropriately for the import data */
/* todo code a new_synchronized_map() constructor and use it here */
if (is_this_a_set)
expmap = new_etch_set(listcount);
else expmap = new_etch_map(listcount / 2);
expmap->content_obj_type = implist->content_obj_type;
expmap->content_class_id = implist->content_class_id;
while(i < (const int) listcount) /* copy data objects to the map */
{
objmask* key = arraylist_get(implist, i++);
if (NULL == key) continue;
if (is_this_a_set)
result = etchmap_set_add(expmap, key);
else result = etchmap_map_add(expmap, key, arraylist_get(implist, i++));
if (-1 == result)
etchlog(ETCHIMPX, ETCHLOG_ERROR, "map insert error on key %u", key);
}
return (objmask*) expmap;
}
/**
* new_map_serializer()
* etch_serializer_map constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_map_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_MAP;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_map_export_value;
newobj->import_value = etchserializer_map_import_value;
return newobj;
}
/**
* etch_serializer_map_init()
* static intitializer for map serializer.
* creates the map serializer and installs it to the supplied type.
* @param thistype type of the serializer (map)
*/
int etch_serializer_map_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* keyname = str_keys_values; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_ETCHMAP, CLASSID_ETCH_MAP);
return etch_serializer_init(thistype, keyname, thisclass, c2tmap,
etchvtor_object_get(1), new_map_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* set serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_set_export_value()
* virtual export value for etch set
* @param objval an etch_hashtable containing values to export. caller owns it,
* and presumably will destroy it on return from this method. this method marks
* the map object such that it will not destroy its content objects.
* @return the exported structvalue object in which the lone entry is an
* etch_arrayvalue containing the map keys
* caller owns memory for the returned object.
*/
objmask* etchserializer_set_export_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_map_export_value(thisx, objval); /* caller owns */
}
/**
* etchserializer_set_import_value()
* virtual import value for etch set.
* @param objval an etch_structvalue of type etch set, wrapping a single entry
* of etch_arrayvalue, wrapping an etch_arraylist containing the set values.
* this method will mark the arraylist such that it will not destroy its content.
* caller retains ownership of this object as with all imports.
* @return a disposable etch_hashtable containing the imported data objects.
* caller must cast it and destroy it.
* note that the c binding works a bit differently that does the java here.
* java tdi populates the structvalue with an object[]. in c the tdi inserts a
* synchronized etch_arraylist wrapped by an etch_arrayvalue, to the structvalue.
*/
objmask* etchserializer_set_import_value(etch_serializer* thisx, objmask* objval)
{
return etchserializer_map_import_value(thisx, objval);
}
/**
* new_set_serializer()
* etch_serializer_set constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_set_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_SET;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_set_export_value;
newobj->import_value = etchserializer_set_import_value;
return newobj;
}
/**
* etch_serializer_set_init()
* static intitializer for set serializer.
* creates the set serializer and installs it to the supplied type.
* @param thistype type of the serializer (set)
*/
int etch_serializer_set_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* keyname = str_keys; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_HASHTABLE, CLASSID_ETCH_SET);
return etch_serializer_init(thistype, keyname, thisclass, c2tmap,
etchvtor_object_get(1), new_set_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* date serializer
* - - - - - - - - - - - - - - - - - -
*/
/**
* etchserializer_date_export_value()
* virtual export value for date
* @param objval an etch_date object for export to tdo.
* caller retains ownership of this object.
* @return the exported structvalue object. caller owns it and must cast it.
*/
objmask* etchserializer_date_export_value(etch_serializer* thisx, objmask* objval)
{
const int THISINITSIZE = 2;
etch_structvalue* expstruct = NULL;
if (!is_etch_date(objval)) return NULL;
expstruct = new_structvalue((etch_type*) thisx->type, THISINITSIZE);
/* assign ownership of the wrapped 64-bit integer to the struct */
structvalue_put(expstruct, clone_field(thisx->field),
(objmask*) new_int64(((etch_date*)objval)->value));
return (objmask*) expstruct; /* caller owns this structvalue */
}
/**
* etchserializer_date_import_value()
* virtual import value for etch date.
* @param objval an etch_structvalue of type etch date.
* caller retains ownership of this object as with all imports.
* @return a *disposable* etch_date object
*/
objmask* etchserializer_date_import_value(etch_serializer* thisx, objmask* objval)
{
etch_date* outdate = NULL;
etch_int64* timeval = NULL;
etch_structvalue* instruct = NULL;
if (!is_etch_struct(objval)) return NULL;
instruct = (etch_structvalue*) objval;
if (!structvalue_is_type(instruct, thisx->type)) return NULL;
/* fetch the arrayvalue out of the struct. struct owns it */
timeval = (etch_int64*) structvalue_get(instruct, thisx->field);
if (!is_etch_int64(timeval)) return NULL;
outdate = new_date();
outdate->value = (time_t) timeval->value;
return (objmask*) outdate; /* caller owns this object */
}
/**
* new_date_serializer()
* etch_serializer_date constructor
* @param type - not owned
* @param field - not owned
*/
etch_serializer* new_date_serializer(etch_type* type, etch_field* field)
{
etch_serializer* newobj = new_etch_serializer(ETCH_DEFSIZE);
newobj->class_id = CLASSID_SERIALIZER_DATE;
newobj->type = type; /* not owned */
newobj->field = field; /* not owned */
newobj->export_value = etchserializer_date_export_value;
newobj->import_value = etchserializer_date_import_value;
return newobj;
}
/**
* etch_serializer_date_init()
* static intitializer for date serializer.
* creates the date serializer and installs it to the supplied type.
* @param thistype type of the serializer (date)
*/
int etch_serializer_date_init(etch_type* thistype, etch_hashtable* c2tmap)
{
const wchar_t* keyname = str_date_time; /* vf static constant */
const unsigned thisclass
= ETCHMAKECLASS(ETCHTYPEB_PRIMITIVE, CLASSID_DATE);
return etch_serializer_init(thistype, keyname, thisclass, c2tmap,
etchvtor_int64_get(0), new_date_serializer);
}
/* - - - - - - - - - - - - - - - - - -
* misc
* - - - - - - - - - - - - - - - - - -
*/
objmask* etchserializer_defexportval(etch_serializer* s, objmask* x)
{
return NULL;
}
objmask* etchserializer_defimportval (etch_serializer* s, objmask* x)
{
return NULL;
}