diff options
Diffstat (limited to 'src/lib/edoors_particle.c')
-rw-r--r-- | src/lib/edoors_particle.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/src/lib/edoors_particle.c b/src/lib/edoors_particle.c new file mode 100644 index 0000000..468cd5b --- /dev/null +++ b/src/lib/edoors_particle.c @@ -0,0 +1,376 @@ +/* EDOORS + * Copyright (C) 2012 Jérémy Zurcher + * + * 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, see <http://www.gnu.org/licenses/>. + */ + +#include "edoors_particle.h" +#include "edoors_private.h" + +static void update_link_value(Edoors_Particle *particle, const char *field); +static char* add_destination(Edoors_Particle *particle, const char *dst); + +Edoors_Particle* edoors_particle_alloc() +{ + BUILD_INSTANCE(Edoors_Particle,particle); + + particle->ts = 0; + particle->src = NULL; + particle->dst = NULL; + particle->dsts = eina_array_new(EDOORS_PARTICLE_ARRAY_STEP); + particle->cur_dst = 0; + particle->cur_action = NULL; + particle->cur_door = NULL; + particle->cur_room = NULL; + particle->payload = eina_hash_string_small_new((Eina_Free_Cb)&eina_stringshare_del); + particle->merged = NULL; + particle->link_fields = eina_array_new(EDOORS_PARTICLE_ARRAY_STEP); + particle->link_value = NULL; + + return particle; +} + +void edoors_particle_free(Edoors_Particle *particle) +{ + unsigned int i; + Eina_Stringshare *s; + Edoors_Particle *p; + Eina_Inlist *li; + Eina_Array_Iterator it; + + DBG("Particle free 0x%X",PRINTPTR(particle)); + + EINA_ARRAY_ITER_NEXT(particle->dsts, i, s, it) eina_stringshare_del(s); + eina_array_free(particle->dsts); + STRINGSHARE_FREE(particle->cur_action); + STRINGSHARE_FREE(particle->cur_door); + STRINGSHARE_FREE(particle->cur_room); + eina_hash_free(particle->payload); + EINA_INLIST_FOREACH_SAFE(particle->merged, li, p) edoors_particle_free(p); + EINA_ARRAY_ITER_NEXT(particle->link_fields, i, s, it) eina_stringshare_del(s); + eina_array_free(particle->link_fields); + STRINGSHARE_FREE(particle->link_value); + + free(particle); +} + +EAPI void edoors_particle_reset(Edoors_Particle *particle) +{ + unsigned int i; + Eina_Stringshare *s; + Edoors_Particle *p; + Eina_Inlist *li; + Eina_Array_Iterator it; + + particle->ts = 0; + particle->src = NULL; + particle->dst = NULL; + EINA_ARRAY_ITER_NEXT(particle->dsts, i, s, it) eina_stringshare_del(s); + eina_array_clean(particle->dsts); + particle->cur_dst = 0; + STRINGSHARE_FREE(particle->cur_action); + STRINGSHARE_FREE(particle->cur_door); + STRINGSHARE_FREE(particle->cur_room); + eina_hash_free_buckets(particle->payload); + EINA_INLIST_FOREACH_SAFE(particle->merged, li, p) edoors_particle_free(p); + particle->merged = NULL; + EINA_ARRAY_ITER_NEXT(particle->link_fields, i, s, it) eina_stringshare_del(s); + eina_array_clean(particle->link_fields); + STRINGSHARE_FREE(particle->link_value); +} + +EAPI void edoors_particle_init(Edoors_Particle *particle, Edoors_Iota *iota) +{ + particle->src = iota; + particle->ts = time(NULL); +} + +EAPI void edoors_particle_merge(Edoors_Particle *particle, const Edoors_Particle *p) +{ + particle->merged = eina_inlist_append(particle->merged, EINA_INLIST_GET((Edoors_Particle*)p)); +} + +EAPI Eina_Bool edoors_particle_has_dst(Edoors_Particle *particle) +{ + return ( (eina_array_count_get(particle->dsts)>particle->cur_dst) ? EINA_TRUE : EINA_FALSE ); +} + +EAPI Eina_Bool edoors_particle_next_dst(Edoors_Particle *particle) +{ + particle->cur_dst+=1; + return ( (eina_array_count_get(particle->dsts)>particle->cur_dst) ? EINA_TRUE : EINA_FALSE ); +} + +EAPI void edoors_particle_split_dst(Edoors_Particle *particle) +{ + unsigned int l, n; + char *sep, *tmp; + Eina_Stringshare *dst; + + if(!edoors_particle_has_dst(particle)) { + STRINGSHARE_FREE(particle->cur_action); + STRINGSHARE_FREE(particle->cur_door); + STRINGSHARE_FREE(particle->cur_room); + return; + } + + dst = eina_array_data_get(particle->dsts,particle->cur_dst); + l = eina_stringshare_strlen(dst); + + sep = (char*)dst+l-sizeof(char); + for(; (sep!=dst && *sep!=EDOORS_ACTION_SEP ); sep--) /* reverse search for action separator */; + + if(*sep==EDOORS_ACTION_SEP) { + tmp = sep+sizeof(char); + /* action defined */ + if(particle->cur_action) { + if(strcmp(particle->cur_action,tmp)!=0) { + eina_stringshare_del(particle->cur_action); + particle->cur_action = eina_stringshare_add(tmp); + } + /* else : keep the same stringshare */ + } else { + particle->cur_action = eina_stringshare_add(tmp); + } + tmp = sep; + sep = sep-sizeof(char); + } else { + STRINGSHARE_FREE(particle->cur_action); + tmp = (char*)dst+l; + sep = (char*)dst+l-sizeof(char); + } + + for(; (sep!=dst && *sep!=EDOORS_PATH_SEP ); sep--) /* reverse search path for separator */; + + if(sep==dst) { + /* no room */ + n=(tmp-sep); + STRINGSHARE_FREE(particle->cur_room); + } else { + n=(sep-dst); + /* door defined */ + if(particle->cur_room) { + if( eina_stringshare_strlen(particle->cur_room)!=n || strncmp(particle->cur_room,dst,n)!=0) { + eina_stringshare_del(particle->cur_room); + particle->cur_room = eina_stringshare_add_length(dst,n); + } + /* else : keep the same stringshare */ + } else { + particle->cur_room = eina_stringshare_add_length(dst,n); + } + n=(tmp-sep-sizeof(char)); + sep++; + } + /* door defined */ + if(particle->cur_door) { + if( eina_stringshare_strlen(particle->cur_door)!=n || strncmp(particle->cur_door,sep,n)!=0) { + eina_stringshare_del(particle->cur_door); + particle->cur_door = eina_stringshare_add_length(sep,n); + } + /* else : keep the same stringshare */ + } else { + particle->cur_door = eina_stringshare_add_length(sep,n); + } +} + +EAPI void edoors_particle_destination_set(Edoors_Particle *particle, const char *destination) +{ + char *tmp; + + tmp = add_destination(particle,destination); + if(*tmp=='\0' || *tmp==' ' || *tmp==EDOORS_FIELDS_SEP) + particle->cur_dst = eina_array_count_get(particle->dsts)-1; +} + +EAPI void edoors_particle_destinations_add(Edoors_Particle *particle, const char* destinations) +{ + char *dst; + + dst = (char*)destinations; + for(;;) { + dst = add_destination(particle,dst); + for(; (*dst && *dst!=EDOORS_FIELDS_SEP); dst++) /* eat whatever is following */; + if(!*dst) return; + dst++; + } +} + +static char* add_destination(Edoors_Particle *particle, const char *dst) +{ + char *start, *end, *last_path_sep, *action_sep; + Eina_Stringshare *s; + + for(start=(char*)dst; *start && *start==' '; start++) /* eat leading spaces */; + + if(*start=='\0' || *start==EDOORS_FIELDS_SEP) { + ERR("ignore empty destination"); + return start; + } + + if(*start==EDOORS_ACTION_SEP || *start==EDOORS_PATH_SEP ) { + ERR("ignore destination starting with '%c' ",*start); + return start; + } + + last_path_sep = action_sep = NULL; + for(end=start; (*end && *end!=EDOORS_FIELDS_SEP && *end!=' '); end++) { + if(*end==EDOORS_PATH_SEP) { + last_path_sep = end; + } else if(*end==EDOORS_ACTION_SEP) { + if(action_sep) { + ERR("ignore destination with more then 1 '%c' ",EDOORS_ACTION_SEP); + return end; + } + if(last_path_sep==(end-sizeof(char))) { + ERR("ignore destination with '%c%c' ",EDOORS_PATH_SEP,EDOORS_ACTION_SEP); + return end; + } + action_sep = end; + } + } + + if(last_path_sep==(end-sizeof(char)) || action_sep==(end-sizeof(char)) ) { + ERR("ignore destination ending with '%c' ",*(end-sizeof(char))); + return end; + } + + s = eina_stringshare_add_length(start,(end-start)); + eina_array_push(particle->dsts,s); + DBG("add dst >%s<",s); + + return end; +} + +EAPI void edoors_particle_link_fields_set(Edoors_Particle *particle, const char *link_fields) +{ + int n; + unsigned int i; + Eina_Stringshare *s; + Eina_Array_Iterator it; + char *field, *sep; + + EINA_ARRAY_ITER_NEXT(particle->link_fields, i, s, it) eina_stringshare_del(s); + eina_array_clean(particle->link_fields); + + field = (char*)link_fields; + for(; *field;) { + for(; *field==' '; field++) /* eat leading spaces */; + sep = field; + for(; (*sep && *sep!=EDOORS_FIELDS_SEP && *sep!=' '); sep++) /* search field end */; + n = (sep-field); + if(n==0) { + ERR("ignore empty field"); + } else { + s = eina_stringshare_add_length(field,n); + eina_array_push(particle->link_fields,s); + DBG("add field >%s<",s); + } + for(; (*sep && *sep!=EDOORS_FIELDS_SEP); sep++) /* eat whatever following */; + if(!*sep) return; + field = sep+sizeof(char); + } + update_link_value(particle,NULL); +} + +EAPI const char* edoors_particle_data_get(Edoors_Particle *particle, const char* key) +{ + return eina_hash_find(particle->payload,key); +} + +EAPI Eina_Bool edoors_particle_data_set(Edoors_Particle *particle, const char* key, const char* value) +{ + unsigned int i; + Eina_Stringshare *s; + Eina_Array_Iterator it; + + s = eina_stringshare_add(value); + if(!eina_hash_add(particle->payload,key,s)) return EINA_FALSE; + update_link_value(particle,key); + + return EINA_TRUE; +} + +EAPI Eina_Bool edoors_particle_data_del(Edoors_Particle *particle, const char* key) +{ + unsigned int i; + Eina_Stringshare *s; + Eina_Array_Iterator it; + + if(!eina_hash_del(particle->payload,key,NULL)) return EINA_FALSE; + update_link_value(particle,key); + + return EINA_TRUE; +} + +EAPI Eina_Bool edoors_particle_match(Edoors_Particle *particle, const Edoors_Particle *p) +{ + return ( (particle->link_value==p->link_value) ? EINA_TRUE : EINA_FALSE ); +} + +static void update_link_value(Edoors_Particle *particle, const char *field) +{ + unsigned int i; + unsigned int l,t; + Eina_Stringshare *k; + Eina_Stringshare *v; + Eina_Array_Iterator it; + Eina_Bool update; + char tmp[EDOORS_MAX_VALUE_LENGTH]; + char *dst; + + if(field!=NULL) { + /* check if link_value has to be updated */ + update = EINA_FALSE; + EINA_ARRAY_ITER_NEXT(particle->link_fields, i, k, it) { + if(strcmp(field,k)==0) { + update = EINA_TRUE; + break; + } + } + if(!update) return; + } + + t = 1; + dst = tmp; + EINA_ARRAY_ITER_NEXT(particle->link_fields, i, k, it) { + v = eina_hash_find(particle->payload,k); + if(v!=NULL) { + l = strlen(v); + t += l; + if(t>EDOORS_MAX_VALUE_LENGTH) { + ERR("buffer overflow (%d>%d) link_value untouched",t,EDOORS_MAX_VALUE_LENGTH); + return; + } + memcpy(dst,v,l); + dst += l; + } + } + *dst='\0'; + + if(particle->link_value) { + if(t==1) { + eina_stringshare_del(particle->link_value); + particle->link_value = NULL; + } else if(strcmp(particle->link_value,tmp)!=0) { + eina_stringshare_del(particle->link_value); + particle->link_value = eina_stringshare_add(tmp); + } + /* else : keep the same stringshare */ + } else if(t!=1) { + particle->link_value = eina_stringshare_add(tmp); + } + /* else : keep particle->link_value=NULL*/ +} + |