1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 - This software is distributed in the hope that it will be
4 - useful, but with NO WARRANTY OF ANY KIND.
5 - No author or distributor accepts responsibility to anyone for the
6 - consequences of using this software, or for whether it serves any
7 - particular purpose or works at all, unless he or she says so in
8 - writing. Everyone is granted permission to copy, modify and
9 - redistribute this source code, for commercial or non-commercial
10 - purposes, with the following restrictions: (1) the origin of this
11 - source code must not be misrepresented; (2) modified versions must
12 - be plainly marked as such; and (3) this notice may not be removed
13 - or altered from any source or modified source distribution.
14 *====================================================================*/
15
16 /*
17 * boxbasic.c
18 *
19 * Basic 'class' functions for box, boxa and boxaa,
20 * including accessors and serialization.
21 *
22 * Box creation, copy, clone, destruction
23 * BOX *boxCreate()
24 * BOX *boxCopy()
25 * BOX *boxClone()
26 * void boxDestroy()
27 *
28 * Box accessors
29 * l_int32 boxGetGeometry()
30 * l_int32 boxSetGeometry()
31 * l_int32 boxGetRefcount()
32 * l_int32 boxChangeRefcount()
33 *
34 * Boxa creation, copy, destruction
35 * BOXA *boxaCreate()
36 * BOXA *boxaCopy()
37 * void boxaDestroy()
38 *
39 * Boxa array extension
40 * l_int32 boxaAddBox()
41 * l_int32 boxaExtendArray()
42 *
43 * Boxa accessors
44 * l_int32 boxaGetCount()
45 * l_int32 boxaGetBox()
46 * l_int32 boxaGetBoxGeometry()
47 *
48 * Boxa array modifiers
49 * l_int32 boxaReplaceBox()
50 * l_int32 boxaInsertBox()
51 * l_int32 boxaRemoveBox()
52 *
53 * Boxaa creation, copy, destruction
54 * BOXAA *boxaaCreate()
55 * BOXAA *boxaaCopy()
56 * void boxaaDestroy()
57 *
58 * Boxaa array extension
59 * l_int32 boxaaAddBoxa()
60 * l_int32 boxaaExtendArray()
61 *
62 * Boxaa accessors
63 * l_int32 boxaaGetCount()
64 * l_int32 boxaaGetBoxCount()
65 * BOXA *boxaaGetBoxa()
66 *
67 * Boxa array modifiers
68 * l_int32 boxaaReplaceBoxa()
69 * l_int32 boxaaInsertBoxa()
70 * l_int32 boxaaRemoveBoxa()
71 * l_int32 boxaaAddBox()
72 *
73 * Boxaa serialized I/O
74 * BOXAA *boxaaRead()
75 * BOXAA *boxaaReadStream()
76 * l_int32 boxaaWrite()
77 * l_int32 boxaaWriteStream()
78 *
79 * Boxa serialized I/O
80 * BOXA *boxaRead()
81 * BOXA *boxaReadStream()
82 * l_int32 boxaWrite()
83 * l_int32 boxaWriteStream()
84 *
85 * Box print (for debug)
86 * l_int32 boxPrintStreamInfo()
87 *
88 * Backward compatibility old boxaa read functions
89 * BOXAA *boxaaReadVersion2()
90 * BOXAA *boxaaReadStreamVersion2()
91 */
92
93 #include <stdio.h>
94 #include <stdlib.h>
95 #include <string.h>
96 #include "allheaders.h"
97
98 static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* n'import quoi */
99
100
101 /*---------------------------------------------------------------------*
102 * Box creation, destruction and copy *
103 *---------------------------------------------------------------------*/
104 /*!
105 * boxCreate()
106 *
107 * Input: x, y, width, height
108 * Return: box, or null on error
109 *
110 * Notes:
111 * (1) This clips the box to the +quad. If no part of the
112 * box is in the +quad, this returns NULL.
113 */
114 BOX *
boxCreate(l_int32 x,l_int32 y,l_int32 w,l_int32 h)115 boxCreate(l_int32 x,
116 l_int32 y,
117 l_int32 w,
118 l_int32 h)
119 {
120 BOX *box;
121
122 PROCNAME("boxCreate");
123
124 if (w <= 0 || h <= 0)
125 return (BOX *)ERROR_PTR("w and h not both > 0", procName, NULL);
126 if (x < 0) { /* take part in +quad */
127 w = w + x;
128 x = 0;
129 if (w <= 0)
130 return (BOX *)ERROR_PTR("x < 0 and box off +quad", procName, NULL);
131 }
132 if (y < 0) { /* take part in +quad */
133 h = h + y;
134 y = 0;
135 if (h <= 0)
136 return (BOX *)ERROR_PTR("y < 0 and box off +quad", procName, NULL);
137 }
138
139 if ((box = (BOX *)CALLOC(1, sizeof(BOX))) == NULL)
140 return (BOX *)ERROR_PTR("box not made", procName, NULL);
141 boxSetGeometry(box, x, y, w, h);
142 box->refcount = 1;
143
144 return box;
145 }
146
147
148 /*!
149 * boxCopy()
150 *
151 * Input: box
152 * Return: copy of box, or null on error
153 */
154 BOX *
boxCopy(BOX * box)155 boxCopy(BOX *box)
156 {
157 BOX *boxc;
158
159 PROCNAME("boxCopy");
160
161 if (!box)
162 return (BOX *)ERROR_PTR("box not defined", procName, NULL);
163
164 boxc = boxCreate(box->x, box->y, box->w, box->h);
165
166 return boxc;
167 }
168
169
170 /*!
171 * boxClone()
172 *
173 * Input: box
174 * Return: ptr to same box, or null on error
175 */
176 BOX *
boxClone(BOX * box)177 boxClone(BOX *box)
178 {
179
180 PROCNAME("boxClone");
181
182 if (!box)
183 return (BOX *)ERROR_PTR("box not defined", procName, NULL);
184
185 boxChangeRefcount(box, 1);
186 return box;
187 }
188
189
190 /*!
191 * boxDestroy()
192 *
193 * Input: &box (<will be set to null before returning>)
194 * Return: void
195 *
196 * Notes:
197 * (1) Decrements the ref count and, if 0, destroys the box.
198 * (2) Always nulls the input ptr.
199 */
200 void
boxDestroy(BOX ** pbox)201 boxDestroy(BOX **pbox)
202 {
203 BOX *box;
204
205 PROCNAME("boxDestroy");
206
207 if (pbox == NULL) {
208 L_WARNING("ptr address is null!", procName);
209 return;
210 }
211 if ((box = *pbox) == NULL)
212 return;
213
214 boxChangeRefcount(box, -1);
215 if (boxGetRefcount(box) <= 0)
216 FREE(box);
217 *pbox = NULL;
218 return;
219 }
220
221
222 /*---------------------------------------------------------------------*
223 * Box accessors *
224 *---------------------------------------------------------------------*/
225 /*!
226 * boxGetGeometry()
227 *
228 * Input: box
229 * &x, &y, &w, &h (<optional return>; each can be null)
230 * Return: 0 if OK, 1 on error
231 */
232 l_int32
boxGetGeometry(BOX * box,l_int32 * px,l_int32 * py,l_int32 * pw,l_int32 * ph)233 boxGetGeometry(BOX *box,
234 l_int32 *px,
235 l_int32 *py,
236 l_int32 *pw,
237 l_int32 *ph)
238 {
239 PROCNAME("boxGetGeometry");
240
241 if (px) *px = 0;
242 if (py) *py = 0;
243 if (pw) *pw = 0;
244 if (ph) *ph = 0;
245 if (!box)
246 return ERROR_INT("box not defined", procName, 1);
247 if (px) *px = box->x;
248 if (py) *py = box->y;
249 if (pw) *pw = box->w;
250 if (ph) *ph = box->h;
251 return 0;
252 }
253
254
255 /*!
256 * boxSetGeometry()
257 *
258 * Input: box
259 * x, y, w, h (use -1 to leave unchanged)
260 * Return: 0 if OK, 1 on error
261 */
262 l_int32
boxSetGeometry(BOX * box,l_int32 x,l_int32 y,l_int32 w,l_int32 h)263 boxSetGeometry(BOX *box,
264 l_int32 x,
265 l_int32 y,
266 l_int32 w,
267 l_int32 h)
268 {
269 PROCNAME("boxSetGeometry");
270
271 if (!box)
272 return ERROR_INT("box not defined", procName, 1);
273 if (x != -1) box->x = x;
274 if (y != -1) box->y = y;
275 if (w != -1) box->w = w;
276 if (h != -1) box->h = h;
277 return 0;
278 }
279
280
281 l_int32
boxGetRefcount(BOX * box)282 boxGetRefcount(BOX *box)
283 {
284 PROCNAME("boxGetRefcount");
285
286 if (!box)
287 return ERROR_INT("box not defined", procName, UNDEF);
288
289 return box->refcount;
290 }
291
292
293 l_int32
boxChangeRefcount(BOX * box,l_int32 delta)294 boxChangeRefcount(BOX *box,
295 l_int32 delta)
296 {
297 PROCNAME("boxChangeRefcount");
298
299 if (!box)
300 return ERROR_INT("box not defined", procName, 1);
301
302 box->refcount += delta;
303 return 0;
304 }
305
306
307 /*---------------------------------------------------------------------*
308 * Boxa creation, destruction, copy, extension *
309 *---------------------------------------------------------------------*/
310 /*!
311 * boxaCreate()
312 *
313 * Input: n (initial number of ptrs)
314 * Return: boxa, or null on error
315 */
316 BOXA *
boxaCreate(l_int32 n)317 boxaCreate(l_int32 n)
318 {
319 BOXA *boxa;
320
321 PROCNAME("boxaCreate");
322
323 if (n <= 0)
324 n = INITIAL_PTR_ARRAYSIZE;
325
326 if ((boxa = (BOXA *)CALLOC(1, sizeof(BOXA))) == NULL)
327 return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
328 boxa->n = 0;
329 boxa->nalloc = n;
330 boxa->refcount = 1;
331
332 if ((boxa->box = (BOX **)CALLOC(n, sizeof(BOX *))) == NULL)
333 return (BOXA *)ERROR_PTR("boxa ptrs not made", procName, NULL);
334
335 return boxa;
336 }
337
338
339 /*!
340 * boxaCopy()
341 *
342 * Input: boxa
343 * copyflag (L_COPY, L_CLONE, L_COPY_CLONE)
344 * Return: new boxa, or null on error
345 *
346 * Notes:
347 * (1) See pix.h for description of the copyflag.
348 * (2) The copy-clone makes a new boxa that holds clones of each box.
349 */
350 BOXA *
boxaCopy(BOXA * boxa,l_int32 copyflag)351 boxaCopy(BOXA *boxa,
352 l_int32 copyflag)
353 {
354 l_int32 i;
355 BOX *boxc;
356 BOXA *boxac;
357
358 PROCNAME("boxaCopy");
359
360 if (!boxa)
361 return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
362
363 if (copyflag == L_CLONE) {
364 boxa->refcount++;
365 return boxa;
366 }
367
368 if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
369 return (BOXA *)ERROR_PTR("invalid copyflag", procName, NULL);
370
371 if ((boxac = boxaCreate(boxa->nalloc)) == NULL)
372 return (BOXA *)ERROR_PTR("boxac not made", procName, NULL);
373 for (i = 0; i < boxa->n; i++) {
374 if (copyflag == L_COPY)
375 boxc = boxaGetBox(boxa, i, L_COPY);
376 else /* copy-clone */
377 boxc = boxaGetBox(boxa, i, L_CLONE);
378 boxaAddBox(boxac, boxc, L_INSERT);
379 }
380 return boxac;
381 }
382
383
384 /*!
385 * boxaDestroy()
386 *
387 * Input: &boxa (<will be set to null before returning>)
388 * Return: void
389 *
390 * Note:
391 * - Decrements the ref count and, if 0, destroys the boxa.
392 * - Always nulls the input ptr.
393 */
394 void
boxaDestroy(BOXA ** pboxa)395 boxaDestroy(BOXA **pboxa)
396 {
397 l_int32 i;
398 BOXA *boxa;
399
400 PROCNAME("boxaDestroy");
401
402 if (pboxa == NULL) {
403 L_WARNING("ptr address is null!", procName);
404 return;
405 }
406
407 if ((boxa = *pboxa) == NULL)
408 return;
409
410 /* Decrement the ref count. If it is 0, destroy the boxa. */
411 boxa->refcount--;
412 if (boxa->refcount <= 0) {
413 for (i = 0; i < boxa->n; i++)
414 boxDestroy(&boxa->box[i]);
415 FREE(boxa->box);
416 FREE(boxa);
417 }
418
419 *pboxa = NULL;
420 return;
421 }
422
423
424 /*!
425 * boxaAddBox()
426 *
427 * Input: boxa
428 * box (to be added)
429 * copyflag (L_INSERT, L_COPY, L_CLONE)
430 * Return: 0 if OK, 1 on error
431 */
432 l_int32
boxaAddBox(BOXA * boxa,BOX * box,l_int32 copyflag)433 boxaAddBox(BOXA *boxa,
434 BOX *box,
435 l_int32 copyflag)
436 {
437 l_int32 n;
438 BOX *boxc;
439
440 PROCNAME("boxaAddBox");
441
442 if (!boxa)
443 return ERROR_INT("boxa not defined", procName, 1);
444 if (!box)
445 return ERROR_INT("box not defined", procName, 1);
446
447 if (copyflag == L_INSERT)
448 boxc = box;
449 else if (copyflag == L_COPY)
450 boxc = boxCopy(box);
451 else if (copyflag == L_CLONE)
452 boxc = boxClone(box);
453 else
454 return ERROR_INT("invalid copyflag", procName, 1);
455 if (!boxc)
456 return ERROR_INT("boxc not made", procName, 1);
457
458 n = boxaGetCount(boxa);
459 if (n >= boxa->nalloc)
460 boxaExtendArray(boxa);
461 boxa->box[n] = boxc;
462 boxa->n++;
463
464 return 0;
465 }
466
467
468 /*!
469 * boxaExtendArray()
470 *
471 * Input: boxa
472 * Return: 0 if OK; 1 on error
473 */
474 l_int32
boxaExtendArray(BOXA * boxa)475 boxaExtendArray(BOXA *boxa)
476 {
477
478 PROCNAME("boxaExtendArray");
479
480 if (!boxa)
481 return ERROR_INT("boxa not defined", procName, 1);
482
483 if ((boxa->box = (BOX **)reallocNew((void **)&boxa->box,
484 sizeof(BOX *) * boxa->nalloc,
485 2 * sizeof(BOX *) * boxa->nalloc)) == NULL)
486 return ERROR_INT("new ptr array not returned", procName, 1);
487
488 boxa->nalloc = 2 * boxa->nalloc;
489 return 0;
490 }
491
492
493
494 /*---------------------------------------------------------------------*
495 * Boxa accessors *
496 *---------------------------------------------------------------------*/
497 /*!
498 * boxaGetCount()
499 *
500 * Input: boxa
501 * Return: count, or 0 on error
502 */
503 l_int32
boxaGetCount(BOXA * boxa)504 boxaGetCount(BOXA *boxa)
505 {
506
507 PROCNAME("boxaGetCount");
508
509 if (!boxa)
510 return ERROR_INT("boxa not defined", procName, 0);
511
512 return boxa->n;
513 }
514
515
516 /*!
517 * boxaGetBox()
518 *
519 * Input: boxa
520 * index (to the index-th box)
521 * accessflag (L_COPY or L_CLONE)
522 * Return: box, or null on error
523 */
524 BOX *
boxaGetBox(BOXA * boxa,l_int32 index,l_int32 accessflag)525 boxaGetBox(BOXA *boxa,
526 l_int32 index,
527 l_int32 accessflag)
528 {
529 PROCNAME("boxaGetBox");
530
531 if (!boxa)
532 return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
533 if (index < 0 || index >= boxa->n)
534 return (BOX *)ERROR_PTR("index not valid", procName, NULL);
535
536 if (accessflag == L_COPY)
537 return boxCopy(boxa->box[index]);
538 else if (accessflag == L_CLONE)
539 return boxClone(boxa->box[index]);
540 else
541 return (BOX *)ERROR_PTR("invalid accessflag", procName, NULL);
542 }
543
544
545 /*!
546 * boxaGetBoxGeometry()
547 *
548 * Input: boxa
549 * index (to the index-th box)
550 * &x, &y, &w, &h (<optional return>; each can be null)
551 * Return: 0 if OK, 1 on error
552 */
553 l_int32
boxaGetBoxGeometry(BOXA * boxa,l_int32 index,l_int32 * px,l_int32 * py,l_int32 * pw,l_int32 * ph)554 boxaGetBoxGeometry(BOXA *boxa,
555 l_int32 index,
556 l_int32 *px,
557 l_int32 *py,
558 l_int32 *pw,
559 l_int32 *ph)
560 {
561 BOX *box;
562
563 PROCNAME("boxaGetBoxGeometry");
564
565 if (px) *px = 0;
566 if (py) *py = 0;
567 if (pw) *pw = 0;
568 if (ph) *ph = 0;
569 if (!boxa)
570 return ERROR_INT("boxa not defined", procName, 1);
571 if (index < 0 || index >= boxa->n)
572 return ERROR_INT("index not valid", procName, 1);
573
574 if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
575 return ERROR_INT("box not found!", procName, 1);
576 boxGetGeometry(box, px, py, pw, ph);
577 boxDestroy(&box);
578 return 0;
579 }
580
581
582 /*---------------------------------------------------------------------*
583 * Boxa array modifiers *
584 *---------------------------------------------------------------------*/
585 /*!
586 * boxaReplaceBox()
587 *
588 * Input: boxa
589 * index (to the index-th box)
590 * box (insert to replace existing one)
591 * Return: 0 if OK, 1 on error
592 *
593 * Notes:
594 * (1) In-place replacement of one box.
595 * (2) The previous box at that location is destroyed.
596 */
597 l_int32
boxaReplaceBox(BOXA * boxa,l_int32 index,BOX * box)598 boxaReplaceBox(BOXA *boxa,
599 l_int32 index,
600 BOX *box)
601 {
602 PROCNAME("boxaReplaceBox");
603
604 if (!boxa)
605 return ERROR_INT("boxa not defined", procName, 1);
606 if (index < 0 || index >= boxa->n)
607 return ERROR_INT("index not valid", procName, 1);
608 if (!box)
609 return ERROR_INT("box not defined", procName, 1);
610
611 boxDestroy(&(boxa->box[index]));
612 boxa->box[index] = box;
613 return 0;
614 }
615
616
617 /*!
618 * boxaInsertBox()
619 *
620 * Input: boxa
621 * index (location in boxa to insert new value)
622 * box (new box to be inserted)
623 * Return: 0 if OK, 1 on error
624 *
625 * Notes:
626 * (1) This shifts box[i] --> box[i + 1] for all i >= index,
627 * and then inserts box as box[index].
628 * (2) To insert at the beginning of the array, set index = 0.
629 * (3) To append to the array, it's easier to use boxaAddBox().
630 * (4) This should not be used repeatedly to insert into large arrays,
631 * because the function is O(n).
632 */
633 l_int32
boxaInsertBox(BOXA * boxa,l_int32 index,BOX * box)634 boxaInsertBox(BOXA *boxa,
635 l_int32 index,
636 BOX *box)
637 {
638 l_int32 i, n;
639 BOX **array;
640
641 PROCNAME("boxaInsertBox");
642
643 if (!boxa)
644 return ERROR_INT("boxa not defined", procName, 1);
645 n = boxaGetCount(boxa);
646 if (index < 0 || index > n)
647 return ERROR_INT("index not in {0...n}", procName, 1);
648 if (!box)
649 return ERROR_INT("box not defined", procName, 1);
650
651 if (n >= boxa->nalloc)
652 boxaExtendArray(boxa);
653 array = boxa->box;
654 boxa->n++;
655 for (i = n; i > index; i--)
656 array[i] = array[i - 1];
657 array[index] = box;
658
659 return 0;
660 }
661
662
663 /*!
664 * boxaRemoveBox()
665 *
666 * Input: boxa
667 * index (of box to be removed)
668 * Return: 0 if OK, 1 on error
669 *
670 * Notes:
671 * (1) This removes box[index] and then shifts
672 * box[i] --> box[i - 1] for all i > index.
673 * (2) It should not be used repeatedly to remove boxes from
674 * large arrays, because the function is O(n).
675 */
676 l_int32
boxaRemoveBox(BOXA * boxa,l_int32 index)677 boxaRemoveBox(BOXA *boxa,
678 l_int32 index)
679 {
680 l_int32 i, n;
681 BOX **array;
682
683 PROCNAME("boxaRemoveBox");
684
685 if (!boxa)
686 return ERROR_INT("boxa not defined", procName, 1);
687 n = boxaGetCount(boxa);
688 if (index < 0 || index >= n)
689 return ERROR_INT("index not in {0...n - 1}", procName, 1);
690
691 array = boxa->box;
692 boxDestroy(&array[index]);
693 for (i = index + 1; i < n; i++)
694 array[i - 1] = array[i];
695 array[n - 1] = NULL;
696 boxa->n--;
697
698 return 0;
699 }
700
701
702 /*--------------------------------------------------------------------------*
703 * Boxaa creation, destruction *
704 *--------------------------------------------------------------------------*/
705 /*!
706 * boxaaCreate()
707 *
708 * Input: size of boxa ptr array to be alloc'd (0 for default)
709 * Return: baa, or null on error
710 */
711 BOXAA *
boxaaCreate(l_int32 n)712 boxaaCreate(l_int32 n)
713 {
714 BOXAA *baa;
715
716 PROCNAME("boxaaCreate");
717
718 if (n <= 0)
719 n = INITIAL_PTR_ARRAYSIZE;
720
721 if ((baa = (BOXAA *)CALLOC(1, sizeof(BOXAA))) == NULL)
722 return (BOXAA *)ERROR_PTR("baa not made", procName, NULL);
723 if ((baa->boxa = (BOXA **)CALLOC(n, sizeof(BOXA *))) == NULL)
724 return (BOXAA *)ERROR_PTR("boxa ptr array not made", procName, NULL);
725
726 baa->nalloc = n;
727 baa->n = 0;
728
729 return baa;
730 }
731
732
733 /*!
734 * boxaaCopy()
735 *
736 * Input: baas (input boxaa to be copied)
737 * copyflag (L_COPY, L_CLONE)
738 * Return: baad (new boxaa, composed of copies or clones of the boxa
739 * in baas), or null on error
740 *
741 * Notes:
742 * (1) L_COPY makes a copy of each boxa in baas.
743 * L_CLONE makes a clone of each boxa in baas.
744 */
745 BOXAA *
boxaaCopy(BOXAA * baas,l_int32 copyflag)746 boxaaCopy(BOXAA *baas,
747 l_int32 copyflag)
748 {
749 l_int32 i, n;
750 BOXA *boxa;
751 BOXAA *baad;
752
753 PROCNAME("boxaaCopy");
754
755 if (!baas)
756 return (BOXAA *)ERROR_PTR("baas not defined", procName, NULL);
757 if (copyflag != L_COPY && copyflag != L_CLONE)
758 return (BOXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
759
760 n = boxaaGetCount(baas);
761 baad = boxaaCreate(n);
762 for (i = 0; i < n; i++) {
763 boxa = boxaaGetBoxa(baas, i, copyflag);
764 boxaaAddBoxa(baad, boxa, L_INSERT);
765 }
766
767 return baad;
768 }
769
770
771 /*!
772 * boxaaDestroy()
773 *
774 * Input: &boxaa (<will be set to null before returning>)
775 * Return: void
776 */
777 void
boxaaDestroy(BOXAA ** pbaa)778 boxaaDestroy(BOXAA **pbaa)
779 {
780 l_int32 i;
781 BOXAA *baa;
782
783 PROCNAME("boxaaDestroy");
784
785 if (pbaa == NULL) {
786 L_WARNING("ptr address is NULL!", procName);
787 return;
788 }
789
790 if ((baa = *pbaa) == NULL)
791 return;
792
793 for (i = 0; i < baa->n; i++)
794 boxaDestroy(&baa->boxa[i]);
795 FREE(baa->boxa);
796 FREE(baa);
797 *pbaa = NULL;
798
799 return;
800 }
801
802
803
804 /*--------------------------------------------------------------------------*
805 * Add Boxa to Boxaa *
806 *--------------------------------------------------------------------------*/
807 /*!
808 * boxaaAddBoxa()
809 *
810 * Input: boxaa
811 * boxa (to be added)
812 * copyflag (L_INSERT, L_COPY, L_CLONE)
813 * Return: 0 if OK, 1 on error
814 */
815 l_int32
boxaaAddBoxa(BOXAA * baa,BOXA * ba,l_int32 copyflag)816 boxaaAddBoxa(BOXAA *baa,
817 BOXA *ba,
818 l_int32 copyflag)
819 {
820 l_int32 n;
821 BOXA *bac;
822
823 PROCNAME("boxaaAddBoxa");
824
825 if (!baa)
826 return ERROR_INT("baa not defined", procName, 1);
827 if (!ba)
828 return ERROR_INT("ba not defined", procName, 1);
829 if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
830 return ERROR_INT("invalid copyflag", procName, 1);
831
832 if (copyflag == L_INSERT)
833 bac = ba;
834 else
835 bac = boxaCopy(ba, copyflag);
836
837 n = boxaaGetCount(baa);
838 if (n >= baa->nalloc)
839 boxaaExtendArray(baa);
840 baa->boxa[n] = bac;
841 baa->n++;
842 return 0;
843 }
844
845
846 /*!
847 * boxaaExtendArray()
848 *
849 * Input: boxaa
850 * Return: 0 if OK, 1 on error
851 */
852 l_int32
boxaaExtendArray(BOXAA * baa)853 boxaaExtendArray(BOXAA *baa)
854 {
855
856 PROCNAME("boxaaExtendArray");
857
858 if (!baa)
859 return ERROR_INT("baa not defined", procName, 1);
860
861 if ((baa->boxa = (BOXA **)reallocNew((void **)&baa->boxa,
862 sizeof(BOXA *) * baa->nalloc,
863 2 * sizeof(BOXA *) * baa->nalloc)) == NULL)
864 return ERROR_INT("new ptr array not returned", procName, 1);
865
866 baa->nalloc *= 2;
867 return 0;
868 }
869
870
871 /*----------------------------------------------------------------------*
872 * Boxaa accessors *
873 *----------------------------------------------------------------------*/
874 /*!
875 * boxaaGetCount()
876 *
877 * Input: boxaa
878 * Return: count (number of boxa), or 0 if no boxa or on error
879 */
880 l_int32
boxaaGetCount(BOXAA * baa)881 boxaaGetCount(BOXAA *baa)
882 {
883 PROCNAME("boxaaGetCount");
884
885 if (!baa)
886 return ERROR_INT("baa not defined", procName, 0);
887 return baa->n;
888 }
889
890
891 /*!
892 * boxaaGetBoxCount()
893 *
894 * Input: boxaa
895 * Return: count (number of boxes), or 0 if no boxes or on error
896 */
897 l_int32
boxaaGetBoxCount(BOXAA * baa)898 boxaaGetBoxCount(BOXAA *baa)
899 {
900 BOXA *boxa;
901 l_int32 n, sum, i;
902
903 PROCNAME("boxaaGetBoxCount");
904
905 if (!baa)
906 return ERROR_INT("baa not defined", procName, 0);
907
908 n = boxaaGetCount(baa);
909 for (sum = 0, i = 0; i < n; i++) {
910 boxa = boxaaGetBoxa(baa, i, L_CLONE);
911 sum += boxaGetCount(boxa);
912 boxaDestroy(&boxa);
913 }
914
915 return sum;
916 }
917
918
919 /*!
920 * boxaaGetBoxa()
921 *
922 * Input: boxaa
923 * index (to the index-th boxa)
924 * accessflag (L_COPY or L_CLONE)
925 * Return: boxa, or null on error
926 */
927 BOXA *
boxaaGetBoxa(BOXAA * baa,l_int32 index,l_int32 accessflag)928 boxaaGetBoxa(BOXAA *baa,
929 l_int32 index,
930 l_int32 accessflag)
931 {
932 l_int32 n;
933
934 PROCNAME("boxaaGetBoxa");
935
936 if (!baa)
937 return (BOXA *)ERROR_PTR("baa not defined", procName, NULL);
938 n = boxaaGetCount(baa);
939 if (index < 0 || index >= n)
940 return (BOXA *)ERROR_PTR("index not valid", procName, NULL);
941 if (accessflag != L_COPY && accessflag != L_CLONE)
942 return (BOXA *)ERROR_PTR("invalid accessflag", procName, NULL);
943
944 return boxaCopy(baa->boxa[index], accessflag);
945 }
946
947
948 /*!
949 * boxaaReplaceBoxa()
950 *
951 * Input: boxaa
952 * index (to the index-th boxa)
953 * boxa (insert and replace any existing one)
954 * Return: 0 if OK, 1 on error
955 *
956 * Notes:
957 * (1) Any existing boxa is destroyed, and the input one
958 * is inserted in its place.
959 * (2) If the index is invalid, return 1 (error)
960 */
961 l_int32
boxaaReplaceBoxa(BOXAA * baa,l_int32 index,BOXA * boxa)962 boxaaReplaceBoxa(BOXAA *baa,
963 l_int32 index,
964 BOXA *boxa)
965 {
966 l_int32 n;
967
968 PROCNAME("boxaaReplaceBoxa");
969
970 if (!baa)
971 return ERROR_INT("baa not defined", procName, 1);
972 if (!boxa)
973 return ERROR_INT("boxa not defined", procName, 1);
974 n = boxaaGetCount(baa);
975 if (index < 0 || index >= n)
976 return ERROR_INT("index not valid", procName, 1);
977
978 boxaDestroy(&baa->boxa[index]);
979 baa->boxa[index] = boxa;
980 return 0;
981 }
982
983
984 /*!
985 * boxaaInsertBoxa()
986 *
987 * Input: boxaa
988 * index (location in boxaa to insert new boxa)
989 * boxa (new boxa to be inserted)
990 * Return: 0 if OK, 1 on error
991 *
992 * Notes:
993 * (1) This shifts boxa[i] --> boxa[i + 1] for all i >= index,
994 * and then inserts boxa as boxa[index].
995 * (2) To insert at the beginning of the array, set index = 0.
996 * (3) To append to the array, it's easier to use boxaaAddBoxa().
997 * (4) This should not be used repeatedly to insert into large arrays,
998 * because the function is O(n).
999 */
1000 l_int32
boxaaInsertBoxa(BOXAA * baa,l_int32 index,BOXA * boxa)1001 boxaaInsertBoxa(BOXAA *baa,
1002 l_int32 index,
1003 BOXA *boxa)
1004 {
1005 l_int32 i, n;
1006 BOXA **array;
1007
1008 PROCNAME("boxaaInsertBoxa");
1009
1010 if (!baa)
1011 return ERROR_INT("baa not defined", procName, 1);
1012 n = boxaaGetCount(baa);
1013 if (index < 0 || index > n)
1014 return ERROR_INT("index not in {0...n}", procName, 1);
1015 if (!boxa)
1016 return ERROR_INT("boxa not defined", procName, 1);
1017
1018 if (n >= baa->nalloc)
1019 boxaaExtendArray(baa);
1020 array = baa->boxa;
1021 baa->n++;
1022 for (i = n; i > index; i--)
1023 array[i] = array[i - 1];
1024 array[index] = boxa;
1025
1026 return 0;
1027 }
1028
1029
1030 /*!
1031 * boxaaRemoveBoxa()
1032 *
1033 * Input: boxaa
1034 * index (of the boxa to be removed)
1035 * Return: 0 if OK, 1 on error
1036 *
1037 * Notes:
1038 * (1) This removes boxa[index] and then shifts
1039 * boxa[i] --> boxa[i - 1] for all i > index.
1040 * (2) The removed boxaa is destroyed.
1041 * (2) This should not be used repeatedly on large arrays,
1042 * because the function is O(n).
1043 */
1044 l_int32
boxaaRemoveBoxa(BOXAA * baa,l_int32 index)1045 boxaaRemoveBoxa(BOXAA *baa,
1046 l_int32 index)
1047 {
1048 l_int32 i, n;
1049 BOXA **array;
1050
1051 PROCNAME("boxaaRemoveBox");
1052
1053 if (!baa)
1054 return ERROR_INT("baa not defined", procName, 1);
1055 n = boxaaGetCount(baa);
1056 if (index < 0 || index >= n)
1057 return ERROR_INT("index not valid", procName, 1);
1058
1059 array = baa->boxa;
1060 boxaDestroy(&array[index]);
1061 for (i = index + 1; i < n; i++)
1062 array[i - 1] = array[i];
1063 array[n - 1] = NULL;
1064 baa->n--;
1065
1066 return 0;
1067 }
1068
1069
1070 /*!
1071 * boxaaAddBox()
1072 *
1073 * Input: boxaa
1074 * index (of boxa with boxaa)
1075 * box (to be added)
1076 * accessflag (L_INSERT, L_COPY or L_CLONE)
1077 * Return: 0 if OK, 1 on error
1078 *
1079 * Notes:
1080 * (1) Adds to an existing boxa only.
1081 */
1082 l_int32
boxaaAddBox(BOXAA * baa,l_int32 index,BOX * box,l_int32 accessflag)1083 boxaaAddBox(BOXAA *baa,
1084 l_int32 index,
1085 BOX *box,
1086 l_int32 accessflag)
1087 {
1088 l_int32 n;
1089 BOXA *boxa;
1090 PROCNAME("boxaaAddBox");
1091
1092 if (!baa)
1093 return ERROR_INT("baa not defined", procName, 1);
1094 n = boxaaGetCount(baa);
1095 if (index < 0 || index >= n)
1096 return ERROR_INT("index not valid", procName, 1);
1097 if (accessflag != L_INSERT && accessflag != L_COPY && accessflag != L_CLONE)
1098 return ERROR_INT("invalid accessflag", procName, 1);
1099
1100 boxa = boxaaGetBoxa(baa, index, L_CLONE);
1101 boxaAddBox(boxa, box, accessflag);
1102 boxaDestroy(&boxa);
1103 return 0;
1104 }
1105
1106
1107 /*---------------------------------------------------------------------*
1108 * Boxaa serialized I/O *
1109 *---------------------------------------------------------------------*/
1110 /*!
1111 * boxaaRead()
1112 *
1113 * Input: filename
1114 * Return: boxaa, or null on error
1115 */
1116 BOXAA *
boxaaRead(const char * filename)1117 boxaaRead(const char *filename)
1118 {
1119 FILE *fp;
1120 BOXAA *baa;
1121
1122 PROCNAME("boxaaRead");
1123
1124 if (!filename)
1125 return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL);
1126 if ((fp = fopenReadStream(filename)) == NULL)
1127 return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL);
1128
1129 if ((baa = boxaaReadStream(fp)) == NULL) {
1130 fclose(fp);
1131 return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL);
1132 }
1133
1134 fclose(fp);
1135 return baa;
1136 }
1137
1138
1139 /*!
1140 * boxaaReadStream()
1141 *
1142 * Input: stream
1143 * Return: boxaa, or null on error
1144 */
1145 BOXAA *
boxaaReadStream(FILE * fp)1146 boxaaReadStream(FILE *fp)
1147 {
1148 l_int32 n, i, x, y, w, h, version;
1149 l_int32 ignore;
1150 BOXA *boxa;
1151 BOXAA *baa;
1152
1153 PROCNAME("boxaaReadStream");
1154
1155 if (!fp)
1156 return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL);
1157
1158 if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
1159 return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1160 if (version != BOXAA_VERSION_NUMBER)
1161 return (BOXAA *)ERROR_PTR("invalid boxa version", procName, NULL);
1162 if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
1163 return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1164
1165 if ((baa = boxaaCreate(n)) == NULL)
1166 return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL);
1167
1168 for (i = 0; i < n; i++) {
1169 if (fscanf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1170 &ignore, &x, &y, &w, &h) != 5)
1171 return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL);
1172 if ((boxa = boxaReadStream(fp)) == NULL)
1173 return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL);
1174 boxaaAddBoxa(baa, boxa, L_INSERT);
1175 }
1176
1177 return baa;
1178 }
1179
1180 /*!
1181 * boxaaWrite()
1182 *
1183 * Input: filename
1184 * boxaa
1185 * Return: 0 if OK, 1 on error
1186 */
1187 l_int32
boxaaWrite(const char * filename,BOXAA * baa)1188 boxaaWrite(const char *filename,
1189 BOXAA *baa)
1190 {
1191 FILE *fp;
1192
1193 PROCNAME("boxaaWrite");
1194
1195 if (!filename)
1196 return ERROR_INT("filename not defined", procName, 1);
1197 if (!baa)
1198 return ERROR_INT("baa not defined", procName, 1);
1199
1200 if ((fp = fopen(filename, "w")) == NULL)
1201 return ERROR_INT("stream not opened", procName, 1);
1202 if (boxaaWriteStream(fp, baa))
1203 return ERROR_INT("baa not written to stream", procName, 1);
1204 fclose(fp);
1205
1206 return 0;
1207 }
1208
1209
1210 /*!
1211 * boxaaWriteStream()
1212 *
1213 * Input: stream
1214 * boxaa
1215 * Return: 0 if OK, 1 on error
1216 */
1217 l_int32
boxaaWriteStream(FILE * fp,BOXAA * baa)1218 boxaaWriteStream(FILE *fp,
1219 BOXAA *baa)
1220 {
1221 l_int32 n, i, x, y, w, h;
1222 BOX *box;
1223 BOXA *boxa;
1224
1225 PROCNAME("boxaaWriteStream");
1226
1227 if (!fp)
1228 return ERROR_INT("stream not defined", procName, 1);
1229 if (!baa)
1230 return ERROR_INT("baa not defined", procName, 1);
1231
1232 n = boxaaGetCount(baa);
1233 fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER);
1234 fprintf(fp, "Number of boxa = %d\n", n);
1235
1236 for (i = 0; i < n; i++) {
1237 if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL)
1238 return ERROR_INT("boxa not found", procName, 1);
1239 boxaGetExtent(boxa, NULL, NULL, &box);
1240 boxGetGeometry(box, &x, &y, &w, &h);
1241 fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1242 i, x, y, w, h);
1243 boxaWriteStream(fp, boxa);
1244 boxDestroy(&box);
1245 boxaDestroy(&boxa);
1246 }
1247 return 0;
1248 }
1249
1250
1251 /*---------------------------------------------------------------------*
1252 * Boxa serialized I/O *
1253 *---------------------------------------------------------------------*/
1254 /*!
1255 * boxaRead()
1256 *
1257 * Input: filename
1258 * Return: boxa, or null on error
1259 */
1260 BOXA *
boxaRead(const char * filename)1261 boxaRead(const char *filename)
1262 {
1263 FILE *fp;
1264 BOXA *boxa;
1265
1266 PROCNAME("boxaRead");
1267
1268 if (!filename)
1269 return (BOXA *)ERROR_PTR("filename not defined", procName, NULL);
1270 if ((fp = fopenReadStream(filename)) == NULL)
1271 return (BOXA *)ERROR_PTR("stream not opened", procName, NULL);
1272
1273 if ((boxa = boxaReadStream(fp)) == NULL) {
1274 fclose(fp);
1275 return (BOXA *)ERROR_PTR("boxa not read", procName, NULL);
1276 }
1277
1278 fclose(fp);
1279 return boxa;
1280 }
1281
1282
1283 /*!
1284 * boxaReadStream()
1285 *
1286 * Input: stream
1287 * Return: boxa, or null on error
1288 */
1289 BOXA *
boxaReadStream(FILE * fp)1290 boxaReadStream(FILE *fp)
1291 {
1292 l_int32 n, i, x, y, w, h, version;
1293 l_int32 ignore;
1294 BOX *box;
1295 BOXA *boxa;
1296
1297 PROCNAME("boxaReadStream");
1298
1299 if (!fp)
1300 return (BOXA *)ERROR_PTR("stream not defined", procName, NULL);
1301
1302 if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1)
1303 return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
1304 if (version != BOXA_VERSION_NUMBER)
1305 return (BOXA *)ERROR_PTR("invalid boxa version", procName, NULL);
1306 if (fscanf(fp, "Number of boxes = %d\n", &n) != 1)
1307 return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
1308
1309 if ((boxa = boxaCreate(n)) == NULL)
1310 return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
1311
1312 for (i = 0; i < n; i++) {
1313 if (fscanf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
1314 &ignore, &x, &y, &w, &h) != 5)
1315 return (BOXA *)ERROR_PTR("box descr not valid", procName, NULL);
1316 if ((box = boxCreate(x, y, w, h)) == NULL)
1317 return (BOXA *)ERROR_PTR("box not made", procName, NULL);
1318 boxaAddBox(boxa, box, L_INSERT);
1319 }
1320
1321 return boxa;
1322 }
1323
1324
1325 /*!
1326 * boxaWrite()
1327 *
1328 * Input: filename
1329 * boxa
1330 * Return: 0 if OK, 1 on error
1331 */
1332 l_int32
boxaWrite(const char * filename,BOXA * boxa)1333 boxaWrite(const char *filename,
1334 BOXA *boxa)
1335 {
1336 FILE *fp;
1337
1338 PROCNAME("boxaWrite");
1339
1340 if (!filename)
1341 return ERROR_INT("filename not defined", procName, 1);
1342 if (!boxa)
1343 return ERROR_INT("boxa not defined", procName, 1);
1344
1345 if ((fp = fopen(filename, "w")) == NULL)
1346 return ERROR_INT("stream not opened", procName, 1);
1347 if (boxaWriteStream(fp, boxa))
1348 return ERROR_INT("boxa not written to stream", procName, 1);
1349 fclose(fp);
1350
1351 return 0;
1352 }
1353
1354
1355 /*!
1356 * boxaWriteStream()
1357 *
1358 * Input: stream
1359 * boxa
1360 * Return: 0 if OK, 1 on error
1361 */
1362 l_int32
boxaWriteStream(FILE * fp,BOXA * boxa)1363 boxaWriteStream(FILE *fp,
1364 BOXA *boxa)
1365 {
1366 l_int32 n, i;
1367 BOX *box;
1368
1369 PROCNAME("boxaWriteStream");
1370
1371 if (!fp)
1372 return ERROR_INT("stream not defined", procName, 1);
1373 if (!boxa)
1374 return ERROR_INT("boxa not defined", procName, 1);
1375
1376 n = boxaGetCount(boxa);
1377 fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
1378 fprintf(fp, "Number of boxes = %d\n", n);
1379 for (i = 0; i < n; i++) {
1380 if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
1381 return ERROR_INT("box not found", procName, 1);
1382 fprintf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
1383 i, box->x, box->y, box->w, box->h);
1384 boxDestroy(&box);
1385 }
1386 return 0;
1387 }
1388
1389
1390 /*---------------------------------------------------------------------*
1391 * Debug printing *
1392 *---------------------------------------------------------------------*/
1393 /*!
1394 * boxPrintStreamInfo()
1395 *
1396 * Input: stream
1397 * box
1398 * Return: 0 if OK, 1 on error
1399 *
1400 * Notes:
1401 * (1) This outputs information about the box, for debugging.
1402 * (2) Use serialization functions to write to file if you want
1403 * to read the data back.
1404 */
1405 l_int32
boxPrintStreamInfo(FILE * fp,BOX * box)1406 boxPrintStreamInfo(FILE *fp,
1407 BOX *box)
1408 {
1409 PROCNAME("boxPrintStreamInfo");
1410
1411 if (!fp)
1412 return ERROR_INT("stream not defined", procName, 1);
1413 if (!box)
1414 return ERROR_INT("box not defined", procName, 1);
1415
1416 fprintf(fp, " Box x (pixels) = %d\n", box->x);
1417 fprintf(fp, " Box y (pixels) = %d\n", box->y);
1418 fprintf(fp, " Box width (pixels) = %d\n", box->w);
1419 fprintf(fp, " Box height (pixels) = %d\n", box->h);
1420
1421 return 0;
1422 }
1423
1424
1425
1426 /*---------------------------------------------------------------------*
1427 * Version for reading v.2 boxaa; kept for backward compatibility *
1428 *---------------------------------------------------------------------*/
1429 /*!
1430 * boxaaReadVersion2()
1431 *
1432 * Input: filename
1433 * Return: boxaa, or null on error
1434 *
1435 * Notes:
1436 * (1) These old functions only work on version 2 boxaa.
1437 * They will go to an archive directory sometime after Sept 2009.
1438 * (2) The current format uses BOXAA_VERSION_NUMBER == 3)
1439 */
1440 BOXAA *
boxaaReadVersion2(const char * filename)1441 boxaaReadVersion2(const char *filename)
1442 {
1443 FILE *fp;
1444 BOXAA *baa;
1445
1446 PROCNAME("boxaaReadVersion2");
1447
1448 if (!filename)
1449 return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL);
1450 if ((fp = fopenReadStream(filename)) == NULL)
1451 return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL);
1452
1453 if ((baa = boxaaReadStreamVersion2(fp)) == NULL) {
1454 fclose(fp);
1455 return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL);
1456 }
1457
1458 fclose(fp);
1459 return baa;
1460 }
1461
1462
1463 /*!
1464 * boxaaReadStreamVersion2()
1465 *
1466 * Input: stream
1467 * Return: boxaa, or null on error
1468 *
1469 */
1470 BOXAA *
boxaaReadStreamVersion2(FILE * fp)1471 boxaaReadStreamVersion2(FILE *fp)
1472 {
1473 l_int32 n, i, x, y, w, h, version;
1474 l_int32 ignore;
1475 BOXA *boxa;
1476 BOXAA *baa;
1477
1478 PROCNAME("boxaaReadStreamVersion2");
1479
1480 if (!fp)
1481 return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL);
1482
1483 if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
1484 return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1485 if (version != 2) {
1486 fprintf(stderr, "This is version %d\n", version);
1487 return (BOXAA *)ERROR_PTR("Not old version 2", procName, NULL);
1488 }
1489 if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
1490 return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1491
1492 if ((baa = boxaaCreate(n)) == NULL)
1493 return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL);
1494
1495 for (i = 0; i < n; i++) {
1496 if (fscanf(fp, " Boxa[%d]: x = %d, y = %d, w = %d, h = %d\n",
1497 &ignore, &x, &y, &w, &h) != 5)
1498 return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL);
1499 if ((boxa = boxaReadStream(fp)) == NULL)
1500 return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL);
1501 boxaaAddBoxa(baa, boxa, L_INSERT);
1502 }
1503
1504 return baa;
1505 }
1506
1507
1508