X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgocr%2Flist.c;fp=lib%2Fgocr%2Flist.c;h=0000000000000000000000000000000000000000;hp=332d2bd3755d7cdff37d0e755acc65bf286cefa6;hb=57b37b6999c742d9749001df3e8694124f2715dc;hpb=c672a4c1f3d6c588e4fc93355f9e89cca773c02d diff --git a/lib/gocr/list.c b/lib/gocr/list.c deleted file mode 100644 index 332d2bd..0000000 --- a/lib/gocr/list.c +++ /dev/null @@ -1,334 +0,0 @@ -/* -This is a Optical-Character-Recognition program -Copyright (C) 2000-2006 Joerg Schulenburg - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - see README for email address - - ***********************************IMPORTANT********************************* - Notes to the developers: read the following notes before using these - functions. - * Be careful when using for_each_data() recursively and calling list_del. - It may mangle with the current[] pointers, and possibly segfault or do an - unpredictable or just undesirable behavior. We have been working on a - solution for this problem, and solved some of the biggest problems. - In a few words, the problem is this: when you delete a node, it may be - the current node of a lower level loop. The current code takes care of - access to previous/next elements of the now defunct node. So, if you do - something like: - - for_each_data(l) { - for_each_data(l) { - list_del(l, header_data); - free(header_data); - } end_for_each(l); -+ tempnode = list_cur_next(l); - } end_for_each(l); - - It will work, even though the current node in the outer loop was deleted. - However, if you replace the line marked with + with the following code: - - tempnode = list_next(l, list_get_current(l)); - - it will break, since list_get_current is likely to return NULL or garbage, - since you deleted header_data(). - Conclusion: use list_del carefully. The best way to avoid this problem is - to not use list_del inside a big stack of loops. - * If you have two elements with the same data, the functions will assume - that the first one is the wanted one. Not a bug, a feature. ;-) - * avoid calling list_prev and list_next. They are intensive and slow - functions. Keep the result in a variable or, if you need something more, - use list_get_element_from_data. - - */ - -#include -#include -#include "list.h" -#include "progress.h" - -void list_init( List *l ) { - if ( !l ) - return; - - l->start.next = &l->stop; - l->stop.previous = &l->start; - l->start.previous = l->stop.next = NULL; - l->start.data = l->stop.data = NULL; - l->current = NULL; - l->level = -1; - l->n = 0; -} - -/* inserts data before data_after. If data_after == NULL, appends. - Returns 1 on error, 0 if OK. */ -int list_ins( List *l, void *data_after, void *data) { - Element *e, *after_element; - - /* test arguments */ - if ( !l || !data ) - return 1; - - if ( !data_after || !l->n ) - return list_app(l, data); - - /* get data_after element */ - if ( !(after_element = list_element_from_data(l, data_after)) ) - return 1; - - /* alloc a new element */ - if( !(e = (Element *)malloc(sizeof(Element))) ) - return 1; - e->data = data; - e->next = after_element; - e->previous = after_element->previous; - after_element->previous->next = e; - after_element->previous = e; - l->n++; - - return 0; -} - -/* appends data to the list. Returns 1 on error, 0 if OK. */ -/* same as list_ins(l,NULL,data) ??? */ -int list_app( List *l, void *data ) { - Element *e; - - if ( !l || !data ) - return 1; - if ( !(e = (Element *)malloc(sizeof(Element))) ) - return 1; - - e->data = data; - e->previous = l->stop.previous; - e->next = l->stop.previous->next; - l->stop.previous->next = e; - l->stop.previous = e; - l->n++; - return 0; -} - -/* returns element associated with data. */ -Element *list_element_from_data( List *l, void *data ) { - Element *temp; - - if ( !l || !data || !l->n) - return NULL; - - temp = l->start.next; - - while ( temp->data != data ) { - if ( !temp || temp==&l->stop ) - return NULL; - temp = temp->next; - } - return temp; -} - -/* deletes (first) element with data from list. User must free data. - Returns 0 if OK, 1 on error. - This is the internal version, that shouldn't be called usually. Use the - list_del() macro instead. - */ -int list_del( List *l, void *data ) { - Element *temp; - int i; - - if (!data) return 1; /* do not delete start or stop element */ - - /* find element associated with data */ - if ( !(temp = list_element_from_data(l, data)) ) - return 1; - - /* test if the deleted node is current in some nested loop, and fix it. */ - for ( i = l->level; i >= 0; i-- ) { - if ( l->current[i] == temp ) { - l->current[i] = temp->previous; - } - } - - temp->previous->next = temp->next; - temp->next->previous = temp->previous; - temp->previous = temp->next = NULL; /* mark as freed */ -/* - fprintf(stderr,"\n# list_del=%p start=%p stop=%p",temp,&l->start,&l->stop); -*/ - - /* and free stuff */ - free(temp); /* element pointing to data, fixed mem-leak 0.41 */ - l->n--; - return 0; -} - -/* frees list. See also list_and_data_free() */ -void list_free( List *l ) { - Element *temp, *temp2; - - if ( !l || !l->n ) - return; - - if ( l->current ) { - free(l->current); - } - l->current = NULL; - - temp = l->start.next; - while ( temp && temp!=&l->stop) { - temp2 = temp->next; - free(temp); - temp = temp2; - } - l->start.next = &l->stop; - l->stop.previous = &l->start; -} - -/* setup a new level of for_each */ -int list_higher_level( List *l ) { - Element **newcur; - - if ( !l ) return(1); - - /* - Security-check: NULL pointer passed to realloc. - ANSI allows this, but it may cause portability problems. - */ - newcur = (Element **)realloc(l->current, (l->level+2)*sizeof(Element *)); - if (newcur) { - l->current = newcur; - l->level++; - l->current[l->level] = l->start.next; - } - g_debug(fprintf(stderr, " level++=%d current[]=%p\n", - l->level, l->current);) - if ( !newcur ) { - fprintf(stderr, " realloc failed! abort\n"); return(1); - } - return 0; -} - -void list_lower_level( List *l ) { - if ( !l ) - return; - - if (!l->level) { - free(l->current); /* calm -lefence */ - l->current = NULL; /* could be important */ - } else { - l->current = (Element **)realloc(l->current, l->level*sizeof(Element *)); - } - l->level--; - g_debug(fprintf(stderr, " level--=%d current[]=%p\n", l->level, - l->current);) -} - -/* returns the next item data */ -void *list_next( List *l, void *data ) { - Element *temp; - - if ( !l || !(temp = list_element_from_data(l, data)) ) - return NULL; - if( !temp->next ) return NULL; - return (temp->next->data); -} - -/* returns the previous item data */ -void *list_prev( List *l, void *data ) { - Element *temp; - - if ( !l || !(temp = list_element_from_data(l, data)) ) - return NULL; - if( !temp->previous ) return NULL; - return (temp->previous->data); -} - -/* Similar to qsort. Sorts list, using the (*compare) function, which is - provided by the user. The comparison function must return an integer less - than, equal to, or greater than zero if the first argument is considered to - be respectively less than, equal to, or greater than the second. - Uses the bubble sort algorithm. - */ -void list_sort( List *l, int (*compare)(const void *, const void *) ) { - Element *temp, *prev; - int i, sorted; - progress_counter_t *pc = NULL; - - if ( !l ) - return; - - /* start progress meter, sorting is slow for huge number of elements */ - /* l->n is the worst case, real time is less or equal estimated time */ - pc = open_progress(l->n,"list_sort"); - - for (i = 0; i < l->n; i++ ) { - sorted = 1; /* Flag for early break */ - for ( temp = l->start.next->next; - temp != NULL && temp != &l->stop; temp = temp->next ) { - if ( temp->previous == &l->start ) continue; - if ( compare((const void *)temp->previous->data, - (const void *)temp->data) > 0 ) { - - sorted = 0; /* rest flag */ - /* swap with the previous node */ - prev = temp->previous; - prev->previous->next = temp; - temp->next->previous = prev; - temp->previous = prev->previous; - prev->next = temp->next; - prev->previous = temp; - temp->next = prev; - /* and make sure the node in the for loop is correct */ - temp = prev; - -#ifdef SLOWER_BUT_KEEP_BY_NOW -/* this is a slower version, but guaranteed to work */ - void *data; - - data = temp->data; - prev = temp->previous; - list_del(l, data); - list_ins(l, prev->data, data); - temp = prev; -#endif - } - } - if (sorted) break; - progress(i,pc); /* progress meter */ - } - - close_progress(pc); - g_debug(fprintf(stderr, "list_sort()\n");) -} - -/* calls free_data() for each data in list l, - * before free list with list_free() */ -int list_and_data_free( List *l, void (*free_data)(void *data)) { - void *data; - - if ( !l ) return 0; - if ( !free_data ) return 1; - - for_each_data(l) { - if ((data = list_get_current(l))) - free_data(data); - } end_for_each(l); - - list_free(l); - - g_debug(fprintf(stderr, "list_and_data_free()\n");) - - return 0; -} -