📄 record.c
字号:
/* librecord2 - Record Object manipulation and storage library 2 * * Authors: YE Nan <nan.ye@orange-ftgroup.com> * * This software and associated documentation files (the "Software") * are copyright (C) 2005 LiPS Linux Phone Standards Forum [FranceTelecom] * All Rights Reserved. * * A copyright license is hereby granted for redistribution and use of * the Software in source and binary forms, with or without modification, * provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this copyright license and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this copyright license and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of LiPS nor the names of its Members may be used * to endorse or promote products derived from the Software without * specific prior written permission. * * A patent license for any Necessary Claims owned by Members of LiPS Forum * to make, have made, use, import, offer to sell, lease and sell or otherwise * distribute any implementation compliant with the any specification adopted * by the LiPS Forumcan be obtained from the respective Members on reasonable * and non-discriminatory terms and conditions and under reciprocity, as * regulated in more detail in the Internal Policy of the LiPS Forum. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER, ITS MEMBERS AND CONTRIBUTORS * "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER, * ITS MEMBERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include <stdio.h>#include <glib.h>#include <field.h>#include <template.h>#include <record.h>#include <iterator.h>#include <utils.h>#include "internal.h"/* * FID/FTID maps */typedef struct { GArray *fids; guint32 max_fid; gboolean def_changed;} FidsMap;static FidsMap *fids_map_new (void){ FidsMap *map = NULL; map = g_new0(FidsMap, 1); map->fids = g_array_new(TRUE, TRUE, sizeof(guint32)); map->max_fid = 0; map->def_changed = FALSE; return map;}static voidfids_map_free (FidsMap *map){ utils_g_array_free_generic(map->fids); g_free(map); return;}static voidfids_map_set_fid (FidsMap *map, gint i, guint32 val){ guint32 * dest = &g_array_index(map->fids, guint32, i); *dest = val; return;}#define fids_map_size(map) (map->fids->len)#define fids_map_get_fid(map, i) (g_array_index(map->fids, guint32, i))#define fids_map_get_default_fid(map) (fids_map_get_fid(map, 0))#define fids_map_set_max_fid(map, fid) (map->max_fid = fid)#define fids_map_get_max_fid(map) (map->max_fid)#define fids_map_get_min_fid(map) FID_GENERATE(FID_GET_FTID(fids_map_get_fid(map, 0)), 0)#define fids_map_append_fid(map, fid) (g_array_append_val(map->fids, fid))#define fids_map_prepend_fid(map, fid) (g_array_prepend_val(map->fids, fid))/** * @brief Create a #Record object of specific template. * * @param template the #FieldTemplate objec used to generate * #Record object * * @return newly-created #Record object * or NULL if failed. */Record * record_new (const FieldTemplate *template){ Record * rec = NULL; g_return_val_if_fail(template, NULL); rec = g_new0(Record, 1); rec->fields = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, (GDestroyNotify)field_free); rec->fids_map = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, (GDestroyNotify)fids_map_free); rec->template = template; rec->extended = FALSE; return rec;}/** * @brief Frees the memory allocated for the * #Record object. * * @param record the #Record object */voidrecord_free (Record *record){ g_return_if_fail(record); g_hash_table_destroy(record->fields); g_hash_table_destroy(record->fids_map); g_free(record); return;}static FidsMap *record_gen_base_fields (Record *record, guint32 ftid){ const FieldDescriptor * fdesc = NULL; FidsMap *map = NULL; Iterator * iter = NULL; gint i; /* g_return_val_if_fail(record, FIELD_ID_INVALID); g_return_val_if_fail(ftid != FIELD_TEMPLATE_ID_INVALID, FIELD_ID_INVALID);*/ /* * we need field descriptor(layouts) to generate * default fids of specific ftid. */ fdesc = field_template_get(record->template, ftid); if (fdesc == NULL) { g_print("%s(): INVALID template id: %d\n", __FUNCTION__, ftid); return NULL; } map = fids_map_new(); /* * a newly-generated fid for each layout * in field descriptor */ iter = field_descriptor_get_layouts(fdesc); for (i = 0, iterator_to_first(iter); !iterator_at_last(iter); i++, iterator_next(iter)) { /* * basic fid generation strategy: * FID = FTID * 100 + index; */ guint32 fid_gen = FID_GENERATE(ftid, i); fids_map_append_fid(map, fid_gen); fids_map_set_max_fid(map, fid_gen);// g_array_append_val(map->fids, fid_gen);// map->max_fid = fid_gen; } iterator_free(iter, TRUE); if (TRUE) { guint32 * key = NULL; key = g_new0(guint32, 1); *key = ftid; /* * insert newly-generated fids map to * global hash table of maps. */ g_hash_table_replace(record->fids_map, key, map); } return map;}/** * @brief Add a new field in #Record object for * specific field template * * @param record the #Record object * @param ftid the identifier of field template * * @return identifier of newly-added field in #Record * object. */guint32 record_add_field (Record *record, guint32 ftid){ FieldDescriptor * fdesc = NULL; FidsMap *map = NULL; guint32 fid = FIELD_ID_INVALID; g_return_val_if_fail(record, FIELD_ID_INVALID); g_return_val_if_fail(ftid != FIELD_TEMPLATE_ID_INVALID, FIELD_ID_INVALID); fdesc = field_template_get(record->template, ftid); if (fdesc == NULL) { g_print("%s(): NULL Descriptor (%d).\n", __FUNCTION__, ftid); return FIELD_ID_INVALID; } else if(!(fdesc->attribute & FIELD_ATTR_MULTIPLE)) { g_print("%s(): CANNOT add field for template (%d). MULTI unset.\n", __FUNCTION__, ftid); return FIELD_ID_INVALID; } /* * retrieve existing fids map of specific * ftid. if no existing map, generate one with * default layout. */ map = (FidsMap *)g_hash_table_lookup(record->fids_map, &ftid); if (map == NULL) { map = record_gen_base_fields(record, ftid); } /* * extend fid generation strategy: * FID = MAX_GEN_FID + 1; */ fid = fids_map_get_max_fid(map) + 1; fids_map_append_fid(map, fid); fids_map_set_max_fid(map, fid);// g_array_append_val(map->fids, fid);// map->max_fid = fid; return fid;}/** * @brief Remove a existing field in #Record object for * specific field template * * @param record the #Record object * @param fid the identifier of field to be removed */gboolean record_remove_field (Record *record, guint32 fid){ FidsMap *map = NULL; guint32 ftid = FIELD_TEMPLATE_ID_INVALID; g_return_if_fail(record); g_return_if_fail(fid != FIELD_TEMPLATE_ID_INVALID); ftid = FID_GET_FTID(fid); map = (FidsMap *)g_hash_table_lookup(record->fids_map, &ftid); if (map) { gint i; for (i = 0; i < fids_map_size(map); i++) { guint32 tmp = g_array_index(map->fids, guint32, i);/* g_print("%s: tmp/fid = %d/%d\n", __FUNCTION__, tmp, fid);*/ if (tmp == fid) { break; } }/* g_print("%s(): i = %d, size = %d\n", __FUNCTION__, i, fids_map_size(map));*/ if (i == 0) { g_print("%s(): CANNOT remove default field (%d)\n", __FUNCTION__, fid); return FALSE; } if (i < fids_map_size(map)) { g_array_remove_index(map->fids, i); g_hash_table_remove(record->fields, &fid); } else { g_print("%s(): invalid field (%d)\n", __FUNCTION__, fid); return FALSE; } } else { return FALSE; } return TRUE;}/** * @brief Set value of default field of specific field template * in #Record object. * * @param record the #Record object * @param ftid the identifier of specific field template * @param value the value to be set * @param size size of value or FIELD_SIZE_AUTO to force the function * calculates the size automatically with field template * definition * * @return TRUE if set successfully */gboolean record_set_field_default (Record *record, guint32 ftid, gconstpointer value, FieldSize size){ Field * field = NULL; FidsMap * map = NULL; guint32 fid = FIELD_ID_INVALID; g_return_val_if_fail(record, FALSE); g_return_val_if_fail(ftid != FIELD_TEMPLATE_ID_INVALID, FALSE); map = (FidsMap *)g_hash_table_lookup(record->fids_map, &ftid); if (map == NULL) { map = record_gen_base_fields(record, ftid); } fid = fids_map_get_default_fid(map); field = g_hash_table_lookup(record->fields, &fid); if (field == NULL) { FieldDescriptor *fdesc = NULL; guint32 * key = NULL; fdesc = field_template_get(record->template, ftid); key = g_new0(guint32, 1); *key = fid; field = field_new(fdesc); g_hash_table_replace(record->fields, key, (gpointer)field); } field_set_value(field, value, size); return TRUE;};/** * @brief Set value of field in #Record object. * * @param record the #Record object * @param fid the identifier of the field * @param value the value to be set * @param size size of value or FIELD_SIZE_AUTO to force the function * calculates the size automatically with field template * definition * * @return TRUE if set successfully */gboolean record_set_field (Record *record, guint32 fid, gconstpointer value, FieldSize size){ Field * field = NULL; g_return_val_if_fail(record, FALSE); field = g_hash_table_lookup(record->fields, &fid); if (field == NULL) { FidsMap * map = NULL; guint32 * key = NULL; guint32 ftid = FIELD_TEMPLATE_ID_INVALID; FieldDescriptor * fdesc = NULL; ftid = FID_GET_FTID(fid); g_return_val_if_fail(ftid != FIELD_TEMPLATE_ID_INVALID, FALSE); fdesc = field_template_get(record->template, ftid); map = (FidsMap *)g_hash_table_lookup(record->fids_map, &ftid); if (map == NULL) { map = record_gen_base_fields(record, ftid); } if (fid < fids_map_get_min_fid(map) || fid > fids_map_get_max_fid(map)) { return FALSE; } key = g_new0(guint32, 1); *key = fid; field = field_new(fdesc); g_hash_table_replace(record->fields, key, (gpointer)field); if (record->extended == FALSE) { record->extended = (fid != fids_map_get_default_fid(map)); } } field_set_value(field, value, size); return TRUE;}/** * @brief Set label of default field of specific field template * in #Record object. * * @param record the #Record object * @param ftid the identifier of specific field template * @param label the label to be set * * @return TRUE if set successfully */gboolean record_set_label_default (Record *record, guint32 ftid, const gchar *label){ Field * field = NULL; FidsMap * map = NULL; guint32 fid = FIELD_ID_INVALID; g_return_val_if_fail(record, FALSE); g_return_val_if_fail(ftid != FIELD_TEMPLATE_ID_INVALID, FALSE); map = (FidsMap *)g_hash_table_lookup(record->fids_map, &ftid); if (map == NULL) { map = record_gen_base_fields(record, ftid); } fid = fids_map_get_default_fid(map); field = g_hash_table_lookup(record->fields, &fid); if (field == NULL) { FidsMap * map = NULL; guint32 * key = NULL; guint32 ftid = FIELD_TEMPLATE_ID_INVALID; FieldDescriptor * fdesc = NULL; ftid = FID_GET_FTID(fid); g_return_val_if_fail(ftid != FIELD_TEMPLATE_ID_INVALID, FALSE); fdesc = field_template_get(record->template, ftid); map = (FidsMap *)g_hash_table_lookup(record->fids_map, &ftid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -