third-party/leptonica/prog/listtest.c
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- 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.
*====================================================================*/
/*
* listtest.c
*
* This file tests the main functions in the generic
* list facility, given in list.c and list.h.
*
*/
#include "allheaders.h"
int main(int argc,
char **argv)
{
char *filein;
l_int32 i, n, w, h, samecount, count;
BOX *box, *boxc;
BOXA *boxa, *boxan;
DLLIST *head, *tail, *head2, *tail2, *elem, *nextelem;
PIX *pixs;
static char mainName[] = "listtest";
if (argc != 2)
return ERROR_INT(" Syntax: listtest filein", mainName, 1);
filein = argv[1];
boxa = boxan = NULL;
if ((pixs = pixRead(filein)) == NULL)
return ERROR_INT("pix not made", mainName, 1);
/* start with a boxa */
boxa = pixConnComp(pixs, NULL, 4);
n = boxaGetCount(boxa);
/*-------------------------------------------------------*
* Do one of these two ...
*-------------------------------------------------------*/
if (1) {
/* listAddToTail(): make a list by adding to tail */
head = NULL;
tail = NULL;
for (i = 0; i < n; i++) {
box = boxaGetBox(boxa, i, L_CLONE);
listAddToTail(&head, &tail, box);
}
} else {
/* listAddToHead(): make a list by adding to head */
head = NULL;
for (i = 0; i < n; i++) {
box = boxaGetBox(boxa, i, L_CLONE);
listAddToHead(&head, box);
}
}
/* list concatenation */
head2 = NULL; /* cons up 2nd list from null */
tail2 = NULL;
for (i = 0; i < n; i++) {
box = boxaGetBox(boxa, i, L_CLONE);
listAddToTail(&head2, &tail2, box);
}
listJoin(&head, &head2);
count = listGetCount(head);
fprintf(stderr, "%d items in list\n", count);
listReverse(&head);
count = listGetCount(head);
fprintf(stderr, "%d items in reversed list\n", count);
listReverse(&head);
count = listGetCount(head);
fprintf(stderr, "%d items in doubly reversed list\n", count);
boxan = boxaCreate(n);
/*-------------------------------------------------------*
* Then do one of these ...
*-------------------------------------------------------*/
if (1) {
/* Removal of all elements and data from a list,
* without using L_BEGIN_LIST_FORWARD macro */
for (elem = head; elem; elem = nextelem) {
nextelem = elem->next;
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
listRemoveElement(&head, elem);
}
} else if (0) {
/* Removal of all elements and data from a list,
* using L_BEGIN_LIST_FORWARD macro */
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
listRemoveElement(&head, elem);
L_END_LIST
} else if (0) {
/* Removal of all elements and data from a list,
* using L_BEGIN_LIST_REVERSE macro */
tail = listFindTail(head);
L_BEGIN_LIST_REVERSE(tail, elem)
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
listRemoveElement(&head, elem);
L_END_LIST
} else if (0) {
/* boxa and boxan are same when list made with listAddToHead() */
tail = listFindTail(head);
L_BEGIN_LIST_REVERSE(tail, elem)
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
listRemoveElement(&head, elem);
L_END_LIST
for (i = 0, samecount = 0; i < n; i++) {
if (boxa->box[i]->w == boxan->box[i]->w &&
boxa->box[i]->h == boxan->box[i]->h)
samecount++;
}
fprintf(stderr, " num boxes = %d, same count = %d\n",
boxaGetCount(boxa), samecount);
} else if (0) {
/* boxa and boxan are same when list made with listAddToTail() */
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
listRemoveElement(&head, elem);
L_END_LIST
for (i = 0, samecount = 0; i < n; i++) {
if (boxa->box[i]->w == boxan->box[i]->w &&
boxa->box[i]->h == boxan->box[i]->h)
samecount++;
}
fprintf(stderr, " num boxes = %d, same count = %d\n",
boxaGetCount(boxa), samecount);
} else if (0) {
/* Destroy the boxes and then the list */
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxDestroy(&box);
elem->data = NULL;
L_END_LIST
listDestroy(&head);
} else if (0) {
/* listInsertBefore(): inserting a copy BEFORE each element */
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxc = boxCopy(box);
listInsertBefore(&head, elem, boxc);
L_END_LIST
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
L_END_LIST
listDestroy(&head);
} else if (0) {
/* listInsertAfter(): inserting a copy AFTER that element */
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxc = boxCopy(box);
listInsertAfter(&head, elem, boxc);
L_END_LIST
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)elem->data;
boxaAddBox(boxan, box, L_INSERT);
elem->data = NULL;
listRemoveElement(&head, elem);
L_END_LIST
/* listDestroy(&head); */
} else if (0) {
/* Test listRemoveFromHead(), to successively
* remove the head of the list for all elements. */
count = 0;
while (head) {
box = (BOX *)listRemoveFromHead(&head);
boxDestroy(&box);
count++;
}
fprintf(stderr, "removed %d items\n", count);
} else if (0) {
/* Another version to test listRemoveFromHead(), using
* an iterator macro. */
count = 0;
L_BEGIN_LIST_FORWARD(head, elem)
box = (BOX *)listRemoveFromHead(&head);
boxDestroy(&box);
count++;
L_END_LIST
fprintf(stderr, "removed %d items\n", count);
} else if (0) {
/* test listRemoveFromTail(), to successively remove
* the tail of the list for all elements. */
count = 0;
tail = NULL; /* will find tail automatically */
while (head) {
box = (BOX *)listRemoveFromTail(&head, &tail);
boxDestroy(&box);
count++;
}
fprintf(stderr, "removed %d items\n", count);
} else if (0) {
/* another version to test listRemoveFromTail(), using
* an iterator macro. */
count = 0;
tail = listFindTail(head); /* need to initialize tail */
L_BEGIN_LIST_REVERSE(tail, elem)
box = (BOX *)listRemoveFromTail(&head, &tail);
boxDestroy(&box);
count++;
L_END_LIST
fprintf(stderr, "removed %d items\n", count);
} else if (0) {
/* Iterate backwards over the box array, and use
* listFindElement() to find each corresponding data structure
* within the list; then remove it. Should completely
* destroy the list. Note that listFindElement()
* returns the cell without removing it from the list! */
n = boxaGetCount(boxa);
for (i = 0, count = 0; i < n; i++) {
box = boxaGetBox(boxa, n - i - 1, L_CLONE);
if (i % 1709 == 0) boxPrintStreamInfo(stderr, box);
elem = listFindElement(head, box);
boxDestroy(&box);
if (elem) { /* found */
box = (BOX *)listRemoveElement(&head, elem);
if (i % 1709 == 0) boxPrintStreamInfo(stderr, box);
boxDestroy(&box);
count++;
}
}
fprintf(stderr, "removed %d items\n", count);
}
fprintf(stderr, "boxa count = %d; boxan count = %d\n",
boxaGetCount(boxa), boxaGetCount(boxan));
boxaGetExtent(boxa, &w, &h, NULL);
fprintf(stderr, "boxa extent = (%d, %d)\n", w, h);
boxaGetExtent(boxan, &w, &h, NULL);
fprintf(stderr, "boxan extent = (%d, %d)\n", w, h);
pixDestroy(&pixs);
boxaDestroy(&boxa);
boxaDestroy(&boxan);
return 0;
}