Leptonica  1.77.0
Image processing and image analysis suite
ptra.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
121 #include "allheaders.h"
122 
123 static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* n'importe quoi */
124 
125  /* Static function */
126 static l_int32 ptraExtendArray(L_PTRA *pa);
127 
128 
129 /*--------------------------------------------------------------------------*
130  * Ptra creation and destruction *
131  *--------------------------------------------------------------------------*/
138 L_PTRA *
139 ptraCreate(l_int32 n)
140 {
141 L_PTRA *pa;
142 
143  PROCNAME("ptraCreate");
144 
145  if (n <= 0)
146  n = INITIAL_PTR_ARRAYSIZE;
147 
148  pa = (L_PTRA *)LEPT_CALLOC(1, sizeof(L_PTRA));
149  if ((pa->array = (void **)LEPT_CALLOC(n, sizeof(void *))) == NULL) {
150  ptraDestroy(&pa, 0, 0);
151  return (L_PTRA *)ERROR_PTR("ptr array not made", procName, NULL);
152  }
153  pa->nalloc = n;
154  pa->imax = -1;
155  pa->nactual = 0;
156  return pa;
157 }
158 
159 
184 void
186  l_int32 freeflag,
187  l_int32 warnflag)
188 {
189 l_int32 i, nactual;
190 void *item;
191 L_PTRA *pa;
192 
193  PROCNAME("ptraDestroy");
194 
195  if (ppa == NULL) {
196  L_WARNING("ptr address is NULL\n", procName);
197  return;
198  }
199  if ((pa = *ppa) == NULL)
200  return;
201 
202  ptraGetActualCount(pa, &nactual);
203  if (nactual > 0) {
204  if (freeflag) {
205  for (i = 0; i <= pa->imax; i++) {
206  if ((item = ptraRemove(pa, i, L_NO_COMPACTION)) != NULL)
207  LEPT_FREE(item);
208  }
209  } else if (warnflag) {
210  L_WARNING("potential memory leak of %d items in ptra\n",
211  procName, nactual);
212  }
213  }
214 
215  LEPT_FREE(pa->array);
216  LEPT_FREE(pa);
217  *ppa = NULL;
218  return;
219 }
220 
221 
222 /*--------------------------------------------------------------------------*
223  * Add/insert/remove/replace generic ptr object *
224  *--------------------------------------------------------------------------*/
241 l_ok
243  void *item)
244 {
245 l_int32 imax;
246 
247  PROCNAME("ptraAdd");
248 
249  if (!pa)
250  return ERROR_INT("pa not defined", procName, 1);
251  if (!item)
252  return ERROR_INT("item not defined", procName, 1);
253 
254  ptraGetMaxIndex(pa, &imax);
255  if (imax >= pa->nalloc - 1 && ptraExtendArray(pa))
256  return ERROR_INT("extension failure", procName, 1);
257  pa->array[imax + 1] = (void *)item;
258  pa->imax++;
259  pa->nactual++;
260  return 0;
261 }
262 
263 
270 static l_int32
272 {
273  PROCNAME("ptraExtendArray");
274 
275  if (!pa)
276  return ERROR_INT("pa not defined", procName, 1);
277 
278  if ((pa->array = (void **)reallocNew((void **)&pa->array,
279  sizeof(void *) * pa->nalloc,
280  2 * sizeof(void *) * pa->nalloc)) == NULL)
281  return ERROR_INT("new ptr array not returned", procName, 1);
282 
283  pa->nalloc *= 2;
284  return 0;
285 }
286 
287 
335 l_ok
337  l_int32 index,
338  void *item,
339  l_int32 shiftflag)
340 {
341 l_int32 i, ihole, imax;
342 l_float32 nexpected;
343 
344  PROCNAME("ptraInsert");
345 
346  if (!pa)
347  return ERROR_INT("pa not defined", procName, 1);
348  if (index < 0 || index > pa->nalloc)
349  return ERROR_INT("index not in [0 ... nalloc]", procName, 1);
350  if (shiftflag != L_AUTO_DOWNSHIFT && shiftflag != L_MIN_DOWNSHIFT &&
351  shiftflag != L_FULL_DOWNSHIFT)
352  return ERROR_INT("invalid shiftflag", procName, 1);
353 
354  if (item) pa->nactual++;
355  if (index == pa->nalloc) { /* can happen when index == n */
356  if (ptraExtendArray(pa))
357  return ERROR_INT("extension failure", procName, 1);
358  }
359 
360  /* We are inserting into a hole or adding to the end of the array.
361  * No existing items are moved. */
362  ptraGetMaxIndex(pa, &imax);
363  if (pa->array[index] == NULL) {
364  pa->array[index] = item;
365  if (item && index > imax) /* new item put beyond max so far */
366  pa->imax = index;
367  return 0;
368  }
369 
370  /* We are inserting at the location of an existing item,
371  * forcing the existing item and those below to shift down.
372  * First, extend the array automatically if the last element
373  * (nalloc - 1) is occupied (imax). This may not be necessary
374  * in every situation, but only an anomalous sequence of insertions
375  * into the array would cause extra ptr allocation. */
376  if (imax >= pa->nalloc - 1 && ptraExtendArray(pa))
377  return ERROR_INT("extension failure", procName, 1);
378 
379  /* If there are no holes, do a full downshift.
380  * Otherwise, if L_AUTO_DOWNSHIFT, use the expected number
381  * of holes between index and n to determine the shift mode */
382  if (imax + 1 == pa->nactual) {
383  shiftflag = L_FULL_DOWNSHIFT;
384  } else if (shiftflag == L_AUTO_DOWNSHIFT) {
385  if (imax < 10) {
386  shiftflag = L_FULL_DOWNSHIFT; /* no big deal */
387  } else {
388  nexpected = (l_float32)(imax - pa->nactual) *
389  (l_float32)((imax - index) / imax);
390  shiftflag = (nexpected > 2.0) ? L_MIN_DOWNSHIFT : L_FULL_DOWNSHIFT;
391  }
392  }
393 
394  if (shiftflag == L_MIN_DOWNSHIFT) { /* run down looking for a hole */
395  for (ihole = index + 1; ihole <= imax; ihole++) {
396  if (pa->array[ihole] == NULL)
397  break;
398  }
399  } else { /* L_FULL_DOWNSHIFT */
400  ihole = imax + 1;
401  }
402 
403  for (i = ihole; i > index; i--)
404  pa->array[i] = pa->array[i - 1];
405  pa->array[index] = (void *)item;
406  if (ihole == imax + 1) /* the last item was shifted down */
407  pa->imax++;
408 
409  return 0;
410 }
411 
412 
433 void *
435  l_int32 index,
436  l_int32 flag)
437 {
438 l_int32 i, imax, fromend, icurrent;
439 void *item;
440 
441  PROCNAME("ptraRemove");
442 
443  if (!pa)
444  return (void *)ERROR_PTR("pa not defined", procName, NULL);
445  ptraGetMaxIndex(pa, &imax);
446  if (index < 0 || index > imax)
447  return (void *)ERROR_PTR("index not in [0 ... imax]", procName, NULL);
448 
449  item = pa->array[index];
450  if (item)
451  pa->nactual--;
452  pa->array[index] = NULL;
453 
454  /* If we took the last item, need to reduce pa->n */
455  fromend = (index == imax);
456  if (fromend) {
457  for (i = index - 1; i >= 0; i--) {
458  if (pa->array[i])
459  break;
460  }
461  pa->imax = i;
462  }
463 
464  /* Compact from index to the end of the array */
465  if (!fromend && flag == L_COMPACTION) {
466  for (icurrent = index, i = index + 1; i <= imax; i++) {
467  if (pa->array[i])
468  pa->array[icurrent++] = pa->array[i];
469  }
470  pa->imax = icurrent - 1;
471  }
472  return item;
473 }
474 
475 
482 void *
484 {
485 l_int32 imax;
486 
487  PROCNAME("ptraRemoveLast");
488 
489  if (!pa)
490  return (void *)ERROR_PTR("pa not defined", procName, NULL);
491 
492  /* Remove the last item in the array. No compaction is required. */
493  ptraGetMaxIndex(pa, &imax);
494  if (imax >= 0)
495  return ptraRemove(pa, imax, L_NO_COMPACTION);
496  else /* empty */
497  return NULL;
498 }
499 
500 
511 void *
513  l_int32 index,
514  void *item,
515  l_int32 freeflag)
516 {
517 l_int32 imax;
518 void *olditem;
519 
520  PROCNAME("ptraReplace");
521 
522  if (!pa)
523  return (void *)ERROR_PTR("pa not defined", procName, NULL);
524  ptraGetMaxIndex(pa, &imax);
525  if (index < 0 || index > imax)
526  return (void *)ERROR_PTR("index not in [0 ... imax]", procName, NULL);
527 
528  olditem = pa->array[index];
529  pa->array[index] = item;
530  if (!item && olditem)
531  pa->nactual--;
532  else if (item && !olditem)
533  pa->nactual++;
534 
535  if (freeflag == FALSE)
536  return olditem;
537 
538  if (olditem)
539  LEPT_FREE(olditem);
540  return NULL;
541 }
542 
543 
552 l_ok
554  l_int32 index1,
555  l_int32 index2)
556 {
557 l_int32 imax;
558 void *item;
559 
560  PROCNAME("ptraSwap");
561 
562  if (!pa)
563  return ERROR_INT("pa not defined", procName, 1);
564  if (index1 == index2)
565  return 0;
566  ptraGetMaxIndex(pa, &imax);
567  if (index1 < 0 || index1 > imax || index2 < 0 || index2 > imax)
568  return ERROR_INT("invalid index: not in [0 ... imax]", procName, 1);
569 
570  item = ptraRemove(pa, index1, L_NO_COMPACTION);
571  item = ptraReplace(pa, index2, item, FALSE);
572  ptraInsert(pa, index1, item, L_MIN_DOWNSHIFT);
573  return 0;
574 }
575 
576 
589 l_ok
591 {
592 l_int32 i, imax, nactual, index;
593 
594  PROCNAME("ptraCompactArray");
595 
596  if (!pa)
597  return ERROR_INT("pa not defined", procName, 1);
598  ptraGetMaxIndex(pa, &imax);
599  ptraGetActualCount(pa, &nactual);
600  if (imax + 1 == nactual) return 0;
601 
602  /* Compact the array */
603  for (i = 0, index = 0; i <= imax; i++) {
604  if (pa->array[i])
605  pa->array[index++] = pa->array[i];
606  }
607  pa->imax = index - 1;
608  if (nactual != index)
609  L_ERROR("index = %d; != nactual\n", procName, index);
610 
611  return 0;
612 }
613 
614 
615 /*----------------------------------------------------------------------*
616  * Other array operations *
617  *----------------------------------------------------------------------*/
624 l_ok
626 {
627 l_int32 i, imax;
628 
629  PROCNAME("ptraReverse");
630 
631  if (!pa)
632  return ERROR_INT("pa not defined", procName, 1);
633  ptraGetMaxIndex(pa, &imax);
634 
635  for (i = 0; i < (imax + 1) / 2; i++)
636  ptraSwap(pa, i, imax - i);
637  return 0;
638 }
639 
640 
648 l_ok
650  L_PTRA *pa2)
651 {
652 l_int32 i, imax;
653 void *item;
654 
655  PROCNAME("ptraJoin");
656 
657  if (!pa1)
658  return ERROR_INT("pa1 not defined", procName, 1);
659  if (!pa2)
660  return 0;
661 
662  ptraGetMaxIndex(pa2, &imax);
663  for (i = 0; i <= imax; i++) {
664  item = ptraRemove(pa2, i, L_NO_COMPACTION);
665  ptraAdd(pa1, item);
666  }
667 
668  return 0;
669 }
670 
671 
672 
673 /*----------------------------------------------------------------------*
674  * Simple ptra accessors *
675  *----------------------------------------------------------------------*/
698 l_ok
700  l_int32 *pmaxindex)
701 {
702  PROCNAME("ptraGetMaxIndex");
703 
704  if (!pa)
705  return ERROR_INT("pa not defined", procName, 1);
706  if (!pmaxindex)
707  return ERROR_INT("&maxindex not defined", procName, 1);
708  *pmaxindex = pa->imax;
709  return 0;
710 }
711 
712 
726 l_ok
728  l_int32 *pcount)
729 {
730  PROCNAME("ptraGetActualCount");
731 
732  if (!pa)
733  return ERROR_INT("pa not defined", procName, 1);
734  if (!pcount)
735  return ERROR_INT("&count not defined", procName, 1);
736  *pcount = pa->nactual;
737 
738  return 0;
739 }
740 
741 
758 void *
760  l_int32 index)
761 {
762  PROCNAME("ptraGetPtrToItem");
763 
764  if (!pa)
765  return (void *)ERROR_PTR("pa not defined", procName, NULL);
766  if (index < 0 || index >= pa->nalloc)
767  return (void *)ERROR_PTR("index not in [0 ... nalloc-1]",
768  procName, NULL);
769 
770  return pa->array[index];
771 }
772 
773 
774 /*--------------------------------------------------------------------------*
775  * Ptraa creation and destruction *
776  *--------------------------------------------------------------------------*/
789 L_PTRAA *
790 ptraaCreate(l_int32 n)
791 {
792 L_PTRAA *paa;
793 
794  PROCNAME("ptraaCreate");
795 
796  if (n <= 0)
797  return (L_PTRAA *)ERROR_PTR("n must be > 0", procName, NULL);
798 
799  if ((paa = (L_PTRAA *)LEPT_CALLOC(1, sizeof(L_PTRAA))) == NULL)
800  return (L_PTRAA *)ERROR_PTR("paa not made", procName, NULL);
801  if ((paa->ptra = (L_PTRA **)LEPT_CALLOC(n, sizeof(L_PTRA *))) == NULL) {
802  ptraaDestroy(&paa, 0, 0);
803  return (L_PTRAA *)ERROR_PTR("ptr array not made", procName, NULL);
804  }
805  paa->nalloc = n;
806  return paa;
807 }
808 
809 
825 void
827  l_int32 freeflag,
828  l_int32 warnflag)
829 {
830 l_int32 i, n;
831 L_PTRA *pa;
832 L_PTRAA *paa;
833 
834  PROCNAME("ptraaDestroy");
835 
836  if (ppaa == NULL) {
837  L_WARNING("ptr address is NULL\n", procName);
838  return;
839  }
840  if ((paa = *ppaa) == NULL)
841  return;
842 
843  ptraaGetSize(paa, &n);
844  for (i = 0; i < n; i++) {
845  pa = ptraaGetPtra(paa, i, L_REMOVE);
846  ptraDestroy(&pa, freeflag, warnflag);
847  }
848 
849  LEPT_FREE(paa->ptra);
850  LEPT_FREE(paa);
851  *ppaa = NULL;
852  return;
853 }
854 
855 
856 /*--------------------------------------------------------------------------*
857  * Ptraa accessors *
858  *--------------------------------------------------------------------------*/
866 l_ok
868  l_int32 *psize)
869 {
870  PROCNAME("ptraaGetSize");
871 
872  if (!paa)
873  return ERROR_INT("paa not defined", procName, 1);
874  if (!psize)
875  return ERROR_INT("&size not defined", procName, 1);
876  *psize = paa->nalloc;
877 
878  return 0;
879 }
880 
881 
897 l_ok
899  l_int32 index,
900  L_PTRA *pa)
901 {
902 l_int32 n;
903 
904  PROCNAME("ptraaInsertPtra");
905 
906  if (!paa)
907  return ERROR_INT("paa not defined", procName, 1);
908  if (!pa)
909  return ERROR_INT("pa not defined", procName, 1);
910  ptraaGetSize(paa, &n);
911  if (index < 0 || index >= n)
912  return ERROR_INT("invalid index", procName, 1);
913  if (paa->ptra[index] != NULL)
914  return ERROR_INT("ptra already stored at index", procName, 1);
915 
916  paa->ptra[index] = pa;
917  return 0;
918 }
919 
920 
940 L_PTRA *
942  l_int32 index,
943  l_int32 accessflag)
944 {
945 l_int32 n;
946 L_PTRA *pa;
947 
948  PROCNAME("ptraaGetPtra");
949 
950  if (!paa)
951  return (L_PTRA *)ERROR_PTR("paa not defined", procName, NULL);
952  ptraaGetSize(paa, &n);
953  if (index < 0 || index >= n)
954  return (L_PTRA *)ERROR_PTR("invalid index", procName, NULL);
955  if (accessflag != L_HANDLE_ONLY && accessflag != L_REMOVE)
956  return (L_PTRA *)ERROR_PTR("invalid accessflag", procName, NULL);
957 
958  pa = paa->ptra[index];
959  if (accessflag == L_REMOVE)
960  paa->ptra[index] = NULL;
961  return pa;
962 }
963 
964 
965 /*--------------------------------------------------------------------------*
966  * Ptraa conversion *
967  *--------------------------------------------------------------------------*/
982 L_PTRA *
984 {
985 l_int32 i, n;
986 L_PTRA *pat, *pad;
987 
988  PROCNAME("ptraaFlattenToPtra");
989 
990  if (!paa)
991  return (L_PTRA *)ERROR_PTR("paa not defined", procName, NULL);
992 
993  pad = ptraCreate(0);
994  ptraaGetSize(paa, &n);
995  for (i = 0; i < n; i++) {
996  pat = ptraaGetPtra(paa, i, L_REMOVE);
997  if (!pat) continue;
998  ptraJoin(pad, pat);
999  ptraDestroy(&pat, FALSE, FALSE); /* they're all empty */
1000  }
1001 
1002  return pad;
1003 }
l_ok ptraReverse(L_PTRA *pa)
ptraReverse()
Definition: ptra.c:625
void * ptraGetPtrToItem(L_PTRA *pa, l_int32 index)
ptraGetPtrToItem()
Definition: ptra.c:759
l_ok ptraSwap(L_PTRA *pa, l_int32 index1, l_int32 index2)
ptraSwap()
Definition: ptra.c:553
void ptraaDestroy(L_PTRAA **ppaa, l_int32 freeflag, l_int32 warnflag)
ptraaDestroy()
Definition: ptra.c:826
l_ok ptraGetActualCount(L_PTRA *pa, l_int32 *pcount)
ptraGetActualCount()
Definition: ptra.c:727
Definition: ptra.h:91
l_ok ptraJoin(L_PTRA *pa1, L_PTRA *pa2)
ptraJoin()
Definition: ptra.c:649
void * ptraRemoveLast(L_PTRA *pa)
ptraRemoveLast()
Definition: ptra.c:483
void * reallocNew(void **pindata, l_int32 oldsize, l_int32 newsize)
reallocNew()
Definition: utils2.c:1161
l_ok ptraInsert(L_PTRA *pa, l_int32 index, void *item, l_int32 shiftflag)
ptraInsert()
Definition: ptra.c:336
l_int32 nalloc
Definition: ptra.h:64
L_PTRA * ptraCreate(l_int32 n)
ptraCreate()
Definition: ptra.c:139
L_PTRA * ptraaGetPtra(L_PTRAA *paa, l_int32 index, l_int32 accessflag)
ptraaGetPtra()
Definition: ptra.c:941
l_ok ptraaInsertPtra(L_PTRAA *paa, l_int32 index, L_PTRA *pa)
ptraaInsertPtra()
Definition: ptra.c:898
l_ok ptraCompactArray(L_PTRA *pa)
ptraCompactArray()
Definition: ptra.c:590
l_ok ptraGetMaxIndex(L_PTRA *pa, l_int32 *pmaxindex)
ptraGetMaxIndex()
Definition: ptra.c:699
l_int32 nactual
Definition: ptra.h:55
Definition: ptra.h:51
void * ptraReplace(L_PTRA *pa, l_int32 index, void *item, l_int32 freeflag)
ptraReplace()
Definition: ptra.c:512
l_int32 imax
Definition: ptra.h:54
l_ok ptraaGetSize(L_PTRAA *paa, l_int32 *psize)
ptraaGetSize()
Definition: ptra.c:867
void ptraDestroy(L_PTRA **ppa, l_int32 freeflag, l_int32 warnflag)
ptraDestroy()
Definition: ptra.c:185
l_ok ptraAdd(L_PTRA *pa, void *item)
ptraAdd()
Definition: ptra.c:242
static l_int32 ptraExtendArray(L_PTRA *pa)
ptraExtendArray()
Definition: ptra.c:271
l_int32 nalloc
Definition: ptra.h:53
void * ptraRemove(L_PTRA *pa, l_int32 index, l_int32 flag)
ptraRemove()
Definition: ptra.c:434
L_PTRA * ptraaFlattenToPtra(L_PTRAA *paa)
ptraaFlattenToPtra()
Definition: ptra.c:983
Definition: ptra.h:62
L_PTRAA * ptraaCreate(l_int32 n)
ptraaCreate()
Definition: ptra.c:790
struct L_Ptra ** ptra
Definition: ptra.h:65
void ** array
Definition: ptra.h:56