gsp.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00051 #include <gsp.h>
00052 #include <adt/hash_table.h>
00053 #include <stdlib.h>
00054 #include <stdio.h>
00055 
00056 #define TRANS_TABLE_CHAINS 256
00057 
00058 /*
00059  * Hash table operations for the transition function.
00060  */
00061 
00062 static hash_index_t trans_op_hash(unsigned long key[]);
00063 static int trans_op_compare(unsigned long key[], hash_count_t keys,
00064     link_t *item);
00065 static void trans_op_remove_callback(link_t *item);
00066 
00067 static hash_table_operations_t trans_ops = {
00068         .hash = trans_op_hash,
00069         .compare = trans_op_compare,
00070         .remove_callback = trans_op_remove_callback
00071 };
00072 
00073 static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
00074 static void trans_insert(gsp_t *p, gsp_trans_t *t);
00075 static gsp_trans_t *trans_new(void);
00076 
00078 void gsp_init(gsp_t *p)
00079 {
00080         p->states = 1;
00081         hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
00082 }
00083 
00092 int gsp_insert_defs(gsp_t *p, const int *defs)
00093 {
00094         unsigned mods, key;
00095         const int *dp;
00096         int rc;
00097 
00098         dp = defs;
00099 
00100         while (1) {
00101                 /* Read the output values. */
00102                 mods = *dp++;
00103                 key = *dp++;
00104                 if (key == 0) break;
00105 
00106                 /* Insert one sequence. */              
00107                 rc = gsp_insert_seq(p, dp, mods, key);
00108                 if (rc != 0)
00109                         return rc;
00110 
00111                 /* Skip to the next definition. */
00112                 while (*dp != GSP_END)
00113                         ++dp;
00114                 ++dp;
00115         }
00116 
00117         return 0;
00118 }
00119 
00127 int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
00128 {
00129         int state;
00130         gsp_trans_t *t;
00131 
00132         state = 0;
00133         t = NULL;
00134 
00135         /* Input sequence must be non-empty. */
00136         if (*seq == GSP_END)
00137                 return -1;
00138 
00139         while (*(seq + 1) != GSP_END) {
00140                 t = trans_lookup(p, state, *seq);
00141                 if (t == NULL) {
00142                         /* Create new state. */
00143                         t = trans_new();
00144                         t->old_state = state;
00145                         t->input = *seq;
00146                         t->new_state = p->states++;
00147 
00148                         t->out_mods = 0;
00149                         t->out_key = 0;
00150 
00151                         trans_insert(p, t);
00152                 }
00153                 state = t->new_state;
00154                 ++seq;
00155         }
00156 
00157         /* Process the last transition. */
00158         t = trans_lookup(p, state, *seq);
00159         if (t != NULL) {
00160                 exit(1);
00161                 return -1;      /* Conflicting definition. */
00162         }
00163 
00164         t = trans_new();
00165         t->old_state = state;
00166         t->input = *seq;
00167         t->new_state = 0;
00168 
00169         t->out_mods = mods;
00170         t->out_key = key;
00171 
00172         trans_insert(p, t);
00173 
00174         return 0;
00175 }
00176 
00189 int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
00190 {
00191         gsp_trans_t *t;
00192 
00193         t = trans_lookup(p, state, input);
00194         if (t == NULL) {
00195                 t = trans_lookup(p, state, GSP_DEFAULT);
00196         }
00197 
00198         if (t == NULL) {
00199                 printf("gsp_step: not found\n");
00200                 *mods = 0;
00201                 *key = 0;
00202                 return 0;
00203         }
00204 
00205         *mods = t->out_mods;
00206         *key = t->out_key;
00207         return t->new_state;
00208 }
00209 
00221 static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
00222 {
00223         link_t *item;
00224         unsigned long key[2];
00225 
00226         key[0] = state;
00227         key[1] = input;
00228 
00229         item = hash_table_find(&p->trans, key);
00230         if (item == NULL) return NULL;
00231 
00232         return hash_table_get_instance(item, gsp_trans_t, link);
00233 }
00234 
00240 static void trans_insert(gsp_t *p, gsp_trans_t *t)
00241 {
00242         unsigned long key[2];
00243 
00244         key[0] = t->old_state;
00245         key[1] = t->input;
00246 
00247         hash_table_insert(&p->trans, key, &t->link);
00248 }
00249 
00251 static gsp_trans_t *trans_new(void)
00252 {
00253         gsp_trans_t *t;
00254 
00255         t = malloc(sizeof(gsp_trans_t));
00256         if (t == NULL) {
00257                 printf("Memory allocation failed.\n");
00258                 exit(1);
00259         }
00260 
00261         return t;
00262 }
00263 
00264 /*
00265  * Transition function hash table operations.
00266  */
00267 
00268 static hash_index_t trans_op_hash(unsigned long key[])
00269 {
00270         return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
00271 }
00272 
00273 static int trans_op_compare(unsigned long key[], hash_count_t keys,
00274     link_t *item)
00275 {
00276         gsp_trans_t *t;
00277 
00278         t = hash_table_get_instance(item, gsp_trans_t, link);
00279         return ((key[0] == (unsigned long) t->old_state)
00280             && (key[1] == (unsigned long) t->input));
00281 }
00282 
00283 static void trans_op_remove_callback(link_t *item)
00284 {
00285 }
00286 

Generated on Thu Jun 2 07:45:49 2011 for HelenOS/USB by  doxygen 1.4.7