diff options
Diffstat (limited to 'gfsm/gfsm/src/libgfsm/gfsmAlphabet.c')
-rw-r--r-- | gfsm/gfsm/src/libgfsm/gfsmAlphabet.c | 1026 |
1 files changed, 1026 insertions, 0 deletions
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAlphabet.c b/gfsm/gfsm/src/libgfsm/gfsmAlphabet.c new file mode 100644 index 0000000..078f176 --- /dev/null +++ b/gfsm/gfsm/src/libgfsm/gfsmAlphabet.c @@ -0,0 +1,1026 @@ +/*=============================================================================*\ + * File: gfsmAlphabet.c + * Author: Bryan Jurish <moocow@ling.uni-potsdam.de> + * Description: finite state machine library: alphabet + * + * Copyright (c) 2004-2008 Bryan Jurish. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + *=============================================================================*/ + +#include <gfsmAlphabet.h> +#include <gfsmSet.h> +#include <gfsmUtils.h> +#include <gfsmError.h> + +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> + +/*====================================================================== + * Constants + */ +gfsmUserAlphabetMethods gfsmUserAlphabetDefaultMethods = + { + NULL, //-- key_lookup + NULL, //-- lab_lookup + NULL, //-- insert + //NULL, //-- key_remove + NULL, //-- lab_remove + NULL, //-- key_read + NULL //-- key_write + }; + +/*====================================================================== + * Methods: Constructors + */ + +/*-------------------------------------------------------------- + * new() + */ +gfsmAlphabet *gfsm_alphabet_new(gfsmAType type) +{ + gfsmAlphabet *a=NULL; + switch (type) { + case gfsmATIdentity: + a = (gfsmAlphabet*)g_new0(gfsmIdentityAlphabet,1); + break; + case gfsmATPointer: + a = (gfsmAlphabet*)g_new0(gfsmPointerAlphabet,1); + break; + case gfsmATUser: + a = (gfsmAlphabet*)g_new0(gfsmUserAlphabet,1); + break; + case gfsmATString: + a = (gfsmAlphabet*)g_new0(gfsmStringAlphabet,1); + break; + case gfsmATUnknown: + case gfsmATRange: + default: + a = (gfsmAlphabet*)g_new0(gfsmRangeAlphabet,1); + break; + } + a->type = type; + a->lab_min = gfsmNoLabel; + a->lab_max = gfsmNoLabel; + return a; +} + +/*-------------------------------------------------------------- + * string_new() + */ +/*gfsmAlphabet *gfsm_string_alphabet_new(void) +{ + return gfsm_string_alphabet_init(g_new(gfsmStringAlphabet,1)); + } +*/ + +/*-------------------------------------------------------------- + * init() + */ +gfsmAlphabet *gfsm_alphabet_init(gfsmAlphabet *a) +{ + if (!a) return NULL; + + a->lab_min = gfsmNoLabel; + a->lab_max = gfsmNoLabel; + + switch (a->type) { + case gfsmATIdentity: + return gfsm_identity_alphabet_init((gfsmIdentityAlphabet*)a); + case gfsmATPointer: + return gfsm_pointer_alphabet_init((gfsmPointerAlphabet*)a,NULL,NULL,NULL,NULL); + case gfsmATUser: + return gfsm_user_alphabet_init((gfsmUserAlphabet*)a,NULL,NULL,NULL,NULL, + NULL,&gfsmUserAlphabetDefaultMethods); + case gfsmATString: + return gfsm_string_alphabet_init((gfsmStringAlphabet*)a,FALSE); + case gfsmATUnknown: + case gfsmATRange: + default: + break; + } + return a; +} + +/*-------------------------------------------------------------- + * range_init() + */ +gfsmAlphabet *gfsm_range_alphabet_init (gfsmRangeAlphabet *a, gfsmLabelVal min, gfsmLabelVal max) +{ + a->lab_min = min; + a->lab_max = max; + return a; +} + +/*-------------------------------------------------------------- + * identity_init() + */ +gfsmAlphabet *gfsm_identity_alphabet_init (gfsmIdentityAlphabet *a) +{ + gfsm_range_alphabet_init((gfsmRangeAlphabet*)a, gfsmNoLabel, gfsmNoLabel); + if (!a->labels) a->labels = gfsm_set_new(gfsm_uint_compare); + gfsm_set_clear(a->labels); + return (gfsmAlphabet*)a; +} + +/*-------------------------------------------------------------- + * pointer_init() + */ +gfsmAlphabet *gfsm_pointer_alphabet_init(gfsmPointerAlphabet *a, + gfsmAlphabetKeyDupFunc key_dup_func, + GHashFunc key_hash_func, + GEqualFunc key_equal_func, + GDestroyNotify key_free_func) +{ + gfsm_range_alphabet_init((gfsmRangeAlphabet*)a,gfsmNoLabel,gfsmNoLabel); + + if (a->keys2labels) g_hash_table_destroy(a->keys2labels); + if (a->labels2keys) g_ptr_array_free(a->labels2keys,TRUE); + + a->keys2labels = g_hash_table_new_full(key_hash_func, key_equal_func, key_free_func, NULL); + a->labels2keys = g_ptr_array_new(); + a->key_dup_func = key_dup_func; + + return (gfsmAlphabet*)a; +} + +/*-------------------------------------------------------------- + * string_init() + */ +gfsmAlphabet *gfsm_string_alphabet_init(gfsmStringAlphabet *a, gboolean do_copy) +{ + if (do_copy) + return gfsm_pointer_alphabet_init(a, + (gfsmAlphabetKeyDupFunc)gfsm_alphabet_strdup, + g_str_hash, g_str_equal, g_free); + return gfsm_pointer_alphabet_init(a, NULL, g_str_hash, g_str_equal, NULL); +} + +/*-------------------------------------------------------------- + * user_init() + */ +gfsmAlphabet *gfsm_user_alphabet_init(gfsmUserAlphabet *a, + gfsmAlphabetKeyDupFunc key_dup_func, + GHashFunc key_hash_func, + GEqualFunc key_equal_func, + GDestroyNotify key_destroy_func, + gpointer user_data, + gfsmUserAlphabetMethods *methods) +{ + gfsm_pointer_alphabet_init((gfsmPointerAlphabet*)a, + key_dup_func, + key_hash_func, + key_equal_func, + key_destroy_func); + a->data = user_data; + a->methods = methods ? (*methods) : gfsmUserAlphabetDefaultMethods; + return (gfsmAlphabet*)a; +} + +/*-------------------------------------------------------------- + * clear() + */ +void gfsm_alphabet_clear(gfsmAlphabet *a) +{ + switch (a->type) { + case gfsmATUnknown: + case gfsmATRange: + break; + case gfsmATIdentity: + gfsm_set_clear(((gfsmIdentityAlphabet*)a)->labels); + break; + case gfsmATPointer: + case gfsmATString: + g_ptr_array_set_size(((gfsmPointerAlphabet*)a)->labels2keys,0); + g_hash_table_foreach_remove(((gfsmPointerAlphabet*)a)->keys2labels, gfsm_hash_clear_func, NULL); + break; + case gfsmATUser: + default: + gfsm_alphabet_foreach(a, gfsm_alphabet_foreach_remove_func, NULL); + g_ptr_array_set_size(((gfsmPointerAlphabet*)a)->labels2keys,0); + break; + } + + a->lab_min = gfsmNoLabel; + a->lab_max = gfsmNoLabel; +} + +/*-------------------------------------------------------------- + * gfsm_alphabet_foreach_remove_func() + */ +gboolean gfsm_alphabet_foreach_remove_func(gfsmAlphabet *a, + gpointer key, + gfsmLabelVal lab, + gpointer data) +{ + gfsm_alphabet_remove_label(a,lab); + return FALSE; +} + +/*-------------------------------------------------------------- + * free() + */ +void gfsm_alphabet_free(gfsmAlphabet *a) +{ + switch (a->type) { + case gfsmATIdentity: + gfsm_set_free(((gfsmIdentityAlphabet*)a)->labels); + g_free((gfsmIdentityAlphabet*)a); + return; + case gfsmATUser: + case gfsmATPointer: + case gfsmATString: + g_ptr_array_free(((gfsmPointerAlphabet*)a)->labels2keys,TRUE); + g_hash_table_destroy(((gfsmPointerAlphabet*)a)->keys2labels); + g_free((gfsmPointerAlphabet*)a); + return; + case gfsmATUnknown: + case gfsmATRange: + default: + break; + } + g_free(a); +}; + +/*====================================================================== + * Methods: Utilties + */ + +/*-------------------------------------------------------------- + * gfsm_alphabet_foreach() + */ +gboolean gfsm_alphabet_foreach (gfsmAlphabet *a, + gfsmAlphabetForeachFunc func, + gpointer data) +{ + gfsmLabelVal lab; + gpointer key; + gboolean rc=FALSE; + for (lab = a->lab_min; !rc && lab <= a->lab_max && lab < gfsmNoLabel; lab++) { + if ((key=gfsm_alphabet_find_key(a,lab))==gfsmNoKey) continue; + rc = (*func)(a,key,lab,data); + } + return rc; +} + +/*-------------------------------------------------------------- + * strdup() + */ +gpointer gfsm_alphabet_strdup(gfsmAlphabet *a, const gchar *str) +{ return g_strdup(str); } + +/*====================================================================== + * Methods: Accessors + */ + +/*-------------------------------------------------------------- + * size() + */ +gfsmLabelVal gfsm_alphabet_size(gfsmAlphabet *a) +{ + guint n=0; + switch (a->type) { + case gfsmATIdentity: + return gfsm_set_size(((gfsmIdentityAlphabet*)a)->labels); + case gfsmATUser: + gfsm_alphabet_foreach(a, (gfsmAlphabetForeachFunc)gfsm_alphabet_foreach_size_func, &n); + return (gfsmLabelVal)n; + case gfsmATPointer: + case gfsmATString: + return ((gfsmPointerAlphabet*)a)->labels2keys->len; + case gfsmATUnknown: + case gfsmATRange: + default: + return (a->lab_min != gfsmNoLabel && a->lab_max != gfsmNoLabel + ? (a->lab_max - a->lab_min) + : 0); + } + return n; +} + +/*-------------------------------------------------------------- + * foreach_size_func() + */ +gboolean gfsm_alphabet_foreach_size_func(gfsmAlphabet *a, + gpointer key, + gfsmLabelVal lab, + guint *np) +{ + if (key != gfsmNoKey && lab != gfsmNoLabel) ++(*np); + return FALSE; +} + +/*-------------------------------------------------------------- + * insert() + */ +gfsmLabelVal gfsm_alphabet_insert(gfsmAlphabet *a, gpointer key, gfsmLabelVal label) +{ + switch (a->type) { + + case gfsmATIdentity: + gfsm_set_insert(((gfsmIdentityAlphabet*)a)->labels, key); + label = (gfsmLabelVal) GPOINTER_TO_INT(key); + break; + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.insert) { + if (((gfsmPointerAlphabet*)a)->key_dup_func) { + key = (*(((gfsmPointerAlphabet*)a)->key_dup_func))(((gfsmPointerAlphabet*)a),key); + } + label = (*(((gfsmUserAlphabet*)a)->methods.insert))((gfsmUserAlphabet*)a, key, label); + break; + } + + case gfsmATPointer: + case gfsmATString: + if (label==gfsmNoLabel) + label = ((gfsmPointerAlphabet*)a)->labels2keys->len; + + if (label >= ((gfsmPointerAlphabet*)a)->labels2keys->len) + g_ptr_array_set_size(((gfsmPointerAlphabet*)a)->labels2keys, label+1); + + if (((gfsmPointerAlphabet*)a)->key_dup_func) + key = (*(((gfsmPointerAlphabet*)a)->key_dup_func))(((gfsmPointerAlphabet*)a),key); + + g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys, label) = key; + g_hash_table_insert(((gfsmPointerAlphabet*)a)->keys2labels, key, GUINT_TO_POINTER(label)); + break; + + case gfsmATUnknown: + case gfsmATRange: + default: + break; + } + + //-- range + if (label != gfsmNoLabel) { + if (a->lab_min==gfsmNoLabel || label < a->lab_min) a->lab_min = label; + if (a->lab_max==gfsmNoLabel || label > a->lab_max) a->lab_max = label; + } + + return label; +} + +/*-------------------------------------------------------------- + * get_full() + */ +gfsmLabelVal gfsm_alphabet_get_full(gfsmAlphabet *a, gpointer key, gfsmLabelVal label) +{ + gfsmLabelVal l = gfsm_alphabet_find_label(a,key); + if (l != gfsmNoLabel) { + //-- old mapping exists + if (label == gfsmNoLabel) return l; //-- ... but no new mapping was requested + gfsm_alphabet_remove_label(a,l); + } + return gfsm_alphabet_insert(a,key,label); +} + +/*-------------------------------------------------------------- + * find_label() + */ +gfsmLabelVal gfsm_alphabet_find_label (gfsmAlphabet *a, gconstpointer key) +{ + gpointer k, l; + + switch (a->type) { + + case gfsmATIdentity: + if (gfsm_set_contains(((gfsmIdentityAlphabet*)a)->labels, key)) + return (gfsmLabelVal)GPOINTER_TO_UINT(key); + break; + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.key_lookup) + return (*(((gfsmUserAlphabet*)a)->methods.key_lookup))((gfsmUserAlphabet*)a, key); + + case gfsmATPointer: + case gfsmATString: + if ( g_hash_table_lookup_extended(((gfsmPointerAlphabet*)a)->keys2labels, key, &k, &l) ) + return (gfsmLabelVal)GPOINTER_TO_UINT(l); + break; + + case gfsmATUnknown: + case gfsmATRange: + default: + return ( ((gfsmLabelVal)GPOINTER_TO_UINT(key)) >= a->lab_min + && + ((gfsmLabelVal)GPOINTER_TO_UINT(key)) <= a->lab_max + ? ((gfsmLabelVal)GPOINTER_TO_UINT(key)) + : gfsmNoLabel ); + } + + return gfsmNoLabel; +} + +/*-------------------------------------------------------------- + * find_key + */ +gpointer gfsm_alphabet_find_key(gfsmAlphabet *a, gfsmLabelVal label) +{ + switch (a->type) { + + case gfsmATIdentity: + if ( gfsm_set_contains(((gfsmIdentityAlphabet*)a)->labels, GUINT_TO_POINTER(label)) ) + return GUINT_TO_POINTER(label); + break; + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.lab_lookup) + return (*(((gfsmUserAlphabet*)a)->methods.lab_lookup))((gfsmUserAlphabet*)a, label); + + case gfsmATPointer: + case gfsmATString: + if (label < ((gfsmPointerAlphabet*)a)->labels2keys->len) + return g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys,label); + break; + + case gfsmATUnknown: + case gfsmATRange: + default: + if (label >= a->lab_min && label <= a->lab_max) + return GUINT_TO_POINTER(label); + } + + return gfsmNoKey; +} + +/*-------------------------------------------------------------- + * get_key() + */ +gpointer gfsm_alphabet_get_key(gfsmAlphabet *a, gfsmLabelVal label) +{ + gpointer key; + if (label == gfsmNoLabel) return gfsmNoKey; + + key = gfsm_alphabet_find_key(a,label); + if (key != gfsmNoKey) return key; + gfsm_alphabet_get_full(a, gfsmNoKey, label); + + return gfsmNoKey; +} + +/*-------------------------------------------------------------- + * remove_key() + */ +void gfsm_alphabet_remove_key(gfsmAlphabet *a, gconstpointer key) +{ + gfsmLabelVal label; + + switch (a->type) { + + case gfsmATIdentity: + gfsm_set_remove(((gfsmIdentityAlphabet*)a)->labels, key); + break; + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.lab_remove) { + label = gfsm_alphabet_find_label(a,key); + (*(((gfsmUserAlphabet*)a)->methods.lab_remove))((gfsmUserAlphabet*)a, label); + break; + } + + case gfsmATPointer: + case gfsmATString: + label = gfsm_alphabet_find_label(a,key); + g_hash_table_remove(((gfsmPointerAlphabet*)a)->keys2labels,key); + if (label != gfsmNoLabel && label < ((gfsmPointerAlphabet*)a)->labels2keys->len) { + g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys, label) = NULL; + } + break; + + case gfsmATUnknown: + case gfsmATRange: + default: + break; + } + + //-- ranges + //(missing) +} + +/*-------------------------------------------------------------- + * remove_label() + */ +void gfsm_alphabet_remove_label(gfsmAlphabet *a, gfsmLabelVal label) +{ + gpointer key; + + switch (a->type) { + case gfsmATIdentity: + gfsm_set_remove(((gfsmIdentityAlphabet*)a)->labels, GUINT_TO_POINTER(label)); + break; + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.lab_remove) { + (*(((gfsmUserAlphabet*)a)->methods.lab_remove))((gfsmUserAlphabet*)a, label); + break; + } + + case gfsmATPointer: + case gfsmATString: + if (label < ((gfsmPointerAlphabet*)a)->labels2keys->len) { + key = g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys,label); + g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys,label) = NULL; + g_hash_table_remove(((gfsmPointerAlphabet*)a)->keys2labels,key); + } + break; + + case gfsmATUnknown: + case gfsmATRange: + default: + break; + } +} + +/*-------------------------------------------------------------- + * union() + */ +gfsmAlphabet *gfsm_alphabet_union(gfsmAlphabet *a1, gfsmAlphabet *a2) +{ + gfsm_alphabet_foreach(a2, (gfsmAlphabetForeachFunc)gfsm_alphabet_foreach_union_func, a1); + return a1; +} + +/*-------------------------------------------------------------- + * union_func() + */ +gboolean gfsm_alphabet_foreach_union_func(gfsmAlphabet *src, + gpointer src_key, + gfsmLabelVal src_id, + gfsmAlphabet *dst) +{ + gfsm_alphabet_get_label(dst,src_key); + return FALSE; +} + +/*-------------------------------------------------------------- + * gfsm_alphabet_labels_to_array_func() + */ +gboolean gfsm_alphabet_labels_to_array_func(gfsmAlphabet *alph, + gpointer key, + gfsmLabelVal lab, + GPtrArray *ary) +{ + //g_array_append_val(ary, lab); + g_ptr_array_add(ary, GUINT_TO_POINTER(lab)); + return FALSE; +} + +/*-------------------------------------------------------------- + * gfsm_alphabet_labels_to_array() + */ +void gfsm_alphabet_labels_to_array(gfsmAlphabet *alph, GPtrArray *ary) +{ + gfsm_alphabet_foreach(alph, + (gfsmAlphabetForeachFunc)gfsm_alphabet_labels_to_array_func, + ary); + //return ary; +} + +/*====================================================================== + * Methods: I/O + */ + +/*-------------------------------------------------------------- + * string2key() + */ +gpointer gfsm_alphabet_string2key(gfsmAlphabet *a, GString *gstr) +{ + gpointer key=NULL; + + switch (a->type) { + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.key_read) { + key = (*(((gfsmUserAlphabet*)a)->methods.key_read))((gfsmUserAlphabet*)a, gstr); + break; + } + + case gfsmATPointer: + case gfsmATString: + key = gstr->str; + break; + + case gfsmATUnknown: + case gfsmATRange: + case gfsmATIdentity: + default: + key = (gpointer)strtol(gstr->str,NULL,10); + break; + } + return key; +} + +/*-------------------------------------------------------------- + * key2string() + */ +void gfsm_alphabet_key2string(gfsmAlphabet *a, gpointer key, GString *gstr) +{ + switch (a->type) { + + case gfsmATUser: + if (((gfsmUserAlphabet*)a)->methods.key_write) { + (*(((gfsmUserAlphabet*)a)->methods.key_write))((gfsmUserAlphabet*)a, key, gstr); + break; + } + + case gfsmATPointer: + //-- ? + case gfsmATString: + g_string_assign(gstr,key); + break; + + case gfsmATUnknown: + case gfsmATRange: + case gfsmATIdentity: + default: + g_string_printf(gstr,"%u", GPOINTER_TO_UINT(key)); + break; + } +} + +/*-------------------------------------------------------------- + * load_handle() + */ +gboolean gfsm_alphabet_load_handle (gfsmAlphabet *a, gfsmIOHandle *ioh, gfsmError **errp) +{ + int c; + gpointer key; + gfsmLabelVal label; + GString *s_key = g_string_new(""); + GString *s_lab = g_string_new(""); + + //if (!myname) myname = "gfsm_string_alphabet_load_file()"; + + do { + g_string_truncate(s_key,0); + g_string_truncate(s_lab,0); + + //-- read data fields into temp strings + for (c=gfsmio_getc(ioh); !gfsmio_eof(ioh) && isspace((char)c); c=gfsmio_getc(ioh)) ; + if (gfsmio_eof(ioh)) break; + + for (g_string_append_c(s_key,c), c=gfsmio_getc(ioh); + !gfsmio_eof(ioh) && !isspace((char)c); + c=gfsmio_getc(ioh)) + { + g_string_append_c(s_key,c); + } + + for ( ; !gfsmio_eof(ioh) && isspace((char)c); c=gfsmio_getc(ioh)) ; + if (gfsmio_eof(ioh)) break; + + for (g_string_append_c(s_lab,c), c=gfsmio_getc(ioh); + !gfsmio_eof(ioh) && !isspace((char)c); + c=gfsmio_getc(ioh)) + { + g_string_append_c(s_lab,c); + } + + for ( ; (char)c != '\n' && !gfsmio_eof(ioh); c=gfsmio_getc(ioh) ) ; + + //-- get actual key and label + key = gfsm_alphabet_string2key(a,s_key); + label = strtol(s_lab->str, NULL, 10); + if (gfsm_alphabet_find_label(a,key) != label) { + gfsm_alphabet_remove_key(a, key); + gfsm_alphabet_insert(a, key, label); + } + } while (!gfsmio_eof(ioh)); + + //-- cleanup + g_string_free(s_key,TRUE); + g_string_free(s_lab,TRUE); + return TRUE; +} + + +/*-------------------------------------------------------------- + * load_file() + */ +gboolean gfsm_alphabet_load_file (gfsmAlphabet *a, FILE *f, gfsmError **errp) +{ + gfsmIOHandle *ioh = gfsmio_new_zfile(f,"rb",-1); + gboolean rc = gfsm_alphabet_load_handle(a, ioh, errp); + if (ioh) { + gfsmio_close(ioh); + gfsmio_handle_free(ioh); + } + return rc; +} + +/*-------------------------------------------------------------- + * load_filename() + */ +gboolean gfsm_alphabet_load_filename (gfsmAlphabet *a, const gchar *filename, gfsmError **errp) +{ + gfsmIOHandle *ioh = gfsmio_new_filename(filename, "rb", -1, errp); + gboolean rc = ioh && !(*errp) && gfsm_alphabet_load_handle(a, ioh, errp); + if (ioh) { + gfsmio_close(ioh); + gfsmio_handle_free(ioh); + } + return rc; +} + + + +/*-------------------------------------------------------------- + * save_handle() + */ +gboolean gfsm_alphabet_save_handle(gfsmAlphabet *a, gfsmIOHandle *ioh, gfsmError **errp) +{ + gfsmAlphabetSaveFileData sfdata; + gboolean rc; + sfdata.ioh = ioh; + sfdata.errp = errp; + sfdata.gstr = g_string_new(""); + sfdata.field_sep = "\t"; + sfdata.record_sep = "\n"; + + //-- guts + rc = gfsm_alphabet_foreach(a, (gfsmAlphabetForeachFunc)gfsm_alphabet_save_file_func, &sfdata); + + //-- cleanup + g_string_free(sfdata.gstr,TRUE); + + return !rc; +} + + +/*-------------------------------------------------------------- + * save_file_full() + */ +gboolean gfsm_alphabet_save_file_full(gfsmAlphabet *a, FILE *f, int zlevel, gfsmError **errp) +{ + gfsmIOHandle *ioh = gfsmio_new_zfile(f,"wb",zlevel); + gboolean rc = ioh && !(*errp) && gfsm_alphabet_save_handle(a, ioh, errp); + if (ioh) { + gfsmio_close(ioh); + gfsmio_handle_free(ioh); + } + return rc; +} + +/*-------------------------------------------------------------- + * save_file() + */ +gboolean gfsm_alphabet_save_file(gfsmAlphabet *a, FILE *f, gfsmError **errp) +{ + return gfsm_alphabet_save_file_full(a,f,0,errp); +} + + +/*-------------------------------------------------------------- + * save_filename_full() + */ +gboolean gfsm_alphabet_save_filename_full (gfsmAlphabet *a, const gchar *filename, int zlevel, gfsmError **errp) +{ + gfsmIOHandle *ioh = gfsmio_new_filename(filename,"wb",zlevel,errp); + gboolean rc = ioh && !(*errp) && gfsm_alphabet_save_handle(a, ioh, errp); + if (ioh) { + gfsmio_close(ioh); + gfsmio_handle_free(ioh); + } + return rc; +} + +/*-------------------------------------------------------------- + * save_filename() + */ +gboolean gfsm_alphabet_save_filename (gfsmAlphabet *a, const gchar *filename, gfsmError **errp) +{ + return gfsm_alphabet_save_filename_full(a,filename,0,errp); +} + + +/*-------------------------------------------------------------- + * save_file_func() + */ +gboolean gfsm_alphabet_save_file_func(gfsmAlphabet *a, + gpointer key, + gfsmLabelVal lab, + gfsmAlphabetSaveFileData *sfdata) +{ + gfsm_alphabet_key2string(a,key,sfdata->gstr); + gfsmio_printf(sfdata->ioh, + "%s%s%u%s", + sfdata->gstr->str, sfdata->field_sep, lab, sfdata->record_sep); + return (sfdata->errp && *(sfdata->errp)); +} + + + +/*====================================================================== + * Methods: String Alphabet Utilities + */ + +/*-------------------------------------------------------------- + * gfsm_alphabet_string_to_labels() + */ +gfsmLabelVector *gfsm_alphabet_string_to_labels(gfsmAlphabet *abet, + const gchar *str, + gfsmLabelVector *vec, + gboolean warn_on_undefined) +{ + gfsmLabelVal lab; + const gchar *s = str; + gchar cs[2] = {0,0}; + + //-- setup vector + if (vec==NULL) { + vec = g_ptr_array_sized_new(strlen(str)); + } else { + g_ptr_array_set_size(vec, 0); + } + + for (; *s; s++) { + cs[0] = *s; + lab = gfsm_alphabet_find_label(abet, cs); + + //-- check for non-existant labels + if (lab==gfsmNoLabel) { + if (warn_on_undefined) { + gfsm_carp(g_error_new(g_quark_from_static_string("gfsm"), //--domain + g_quark_from_static_string("gfsm_alphabet_string_to_labels"), //-- code + "Warning: unknown character '%c' in string '%s' -- skipping.", + *s, str)); + } + continue; + } + + g_ptr_array_add(vec, GUINT_TO_POINTER(lab)); + } + + return vec; +} + +/*-------------------------------------------------------------- + * gfsm_alphabet_att_string_to_labels() + */ +gfsmLabelVector *gfsm_alphabet_att_string_to_labels(gfsmAlphabet *abet, + const gchar *str, + gfsmLabelVector *vec, + gboolean warn_on_undefined) +{ + gfsmLabelVal lab; + const gchar *s = str; + GString *gs = g_string_sized_new(4); + gchar mode = 0; + + //-- setup vector + if (vec==NULL) { + vec = g_ptr_array_sized_new(strlen(str)); + } else { + g_ptr_array_set_size(vec, 0); + } + + //-- loop(str): beginning of next symbol + for (; *s; s++) { + switch (mode) { + case '[': + //-- bracket-escape mode + if (*s==']') { mode=0; } + else { g_string_append_c(gs,*s); continue; } + break; + + case '\\': + //-- backslash-escape mode + g_string_append_c(gs,*s); + mode = 0; + break; + + default: + case 0: + //-- outer (unescaped) mode + if (*s == '[') { mode='['; continue; } + else if (*s == '\\') { mode='\\'; continue; } + else if (isspace(*s)) { continue; } //-- ignore spaces + //-- plain single-character symbol: set key-string + g_string_append_c(gs,*s); + break; + } + + //-- lookup key + lab = gfsm_alphabet_find_label(abet, gs->str); + + //-- check for non-existant labels + if (lab==gfsmNoLabel) { + if (warn_on_undefined) { + gfsm_carp(g_error_new(g_quark_from_static_string("gfsm"), //--domain + g_quark_from_static_string("gfsm_alphabet_att_string_to_labels"), //-- code + "Warning: unknown symbol [%s] in string '%s' -- skipping.", + gs->str, str)); + } + g_string_truncate(gs,0); + continue; + } + + //-- add to vector + g_ptr_array_add(vec, GUINT_TO_POINTER(lab)); + g_string_truncate(gs,0); + } + + //-- cleanup + g_string_free(gs,TRUE); + + return vec; +} + +/*-------------------------------------------------------------- + * gfsm_alphabet_generic_string_to_labels() + */ +gfsmLabelVector *gfsm_alphabet_generic_string_to_labels(gfsmAlphabet *abet, + const gchar *str, + gfsmLabelVector *vec, + gboolean warn_on_undefined, + gboolean att_mode) +{ + return (att_mode + ? gfsm_alphabet_att_string_to_labels(abet,str,vec,warn_on_undefined) + : gfsm_alphabet_string_to_labels(abet,str,vec,warn_on_undefined)); +} + + + +/*-------------------------------------------------------------- + * gfsm_alphabet_labels_to_gstring() + */ +GString *gfsm_alphabet_labels_to_gstring(gfsmAlphabet *abet, + gfsmLabelVector *vec, + GString *gstr, + gboolean warn_on_undefined, + gboolean att_style) +{ + gfsmLabelVal lab; + const gchar *sym; + int i; + + //-- setup GString + if (gstr==NULL) { + gstr = g_string_new_len("",vec->len); + } + + //-- lookup & append symbols + for (i=0; i < vec->len; i++) { + lab = (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(vec,i)); + sym = (const gchar*)gfsm_alphabet_find_key(abet,lab); + + //-- check for unknown labels + if (sym==NULL) { + if (warn_on_undefined) { + gfsm_carp(g_error_new(g_quark_from_static_string("gfsm"), //--domain + g_quark_from_static_string("gfsm_alphabet_labels_to_gstring"), //-- code + "Warning: unknown label '%d' -- skipping.", + lab)); + } + continue; + } + + //-- append the symbol to the output string + if (att_style) { + if (strlen(sym)==1) { + g_string_append_c(gstr,sym[0]); + } + else { + g_string_append_c(gstr,'['); + g_string_append(gstr,sym); + g_string_append_c(gstr,']'); + } + } else { //-- !att_style + if (i != 0) g_string_append_c(gstr,' '); + g_string_append(gstr, sym); + } + } + + return gstr; +} + +/*-------------------------------------------------------------- + * gfsm_alphabet_labels_to_string() + */ +char *gfsm_alphabet_labels_to_string(gfsmAlphabet *abet, + gfsmLabelVector *vec, + gboolean warn_on_undefined, + gboolean att_style) +{ + GString *gstr = g_string_new(""); + gfsm_alphabet_labels_to_gstring(abet,vec,gstr,warn_on_undefined,att_style); + char *str = gstr->str; + g_string_free(gstr,FALSE); + return str; +} |