Coverage Report

Created: 2025-06-13 06:48

/src/leptonica/src/dnabasic.c
Line
Count
Source (jump to first uncovered line)
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
27
/*!
28
 * \file  dnabasic.c
29
 * <pre>
30
 *
31
 *      Dna creation, destruction, copy, clone, etc.
32
 *          L_DNA       *l_dnaCreate()
33
 *          L_DNA       *l_dnaCreateFromIArray()
34
 *          L_DNA       *l_dnaCreateFromDArray()
35
 *          L_DNA       *l_dnaMakeSequence()
36
 *          void        *l_dnaDestroy()
37
 *          L_DNA       *l_dnaCopy()
38
 *          L_DNA       *l_dnaClone()
39
 *          l_int32      l_dnaEmpty()
40
 *
41
 *      Dna: add/remove number and extend array
42
 *          l_int32      l_dnaAddNumber()
43
 *          static l_int32  l_dnaExtendArray()
44
 *          l_int32      l_dnaInsertNumber()
45
 *          l_int32      l_dnaRemoveNumber()
46
 *          l_int32      l_dnaReplaceNumber()
47
 *
48
 *      Dna accessors
49
 *          l_int32      l_dnaGetCount()
50
 *          l_int32      l_dnaSetCount()
51
 *          l_int32      l_dnaGetIValue()
52
 *          l_int32      l_dnaGetDValue()
53
 *          l_int32      l_dnaSetValue()
54
 *          l_int32      l_dnaShiftValue()
55
 *          l_int32     *l_dnaGetIArray()
56
 *          l_float64   *l_dnaGetDArray()
57
 *          l_int32      l_dnaGetParameters()
58
 *          l_int32      l_dnaSetParameters()
59
 *          l_int32      l_dnaCopyParameters()
60
 *
61
 *      Serialize Dna for I/O
62
 *          L_DNA       *l_dnaRead()
63
 *          L_DNA       *l_dnaReadStream()
64
 *          L_DNA       *l_dnaReadMem()
65
 *          l_int32      l_dnaWrite()
66
 *          l_int32      l_dnaWriteStream()
67
 *          l_int32      l_dnaWriteStderr()
68
 *          l_int32      l_dnaWriteMem()
69
 *
70
 *      Dnaa creation, destruction
71
 *          L_DNAA      *l_dnaaCreate()
72
 *          L_DNAA      *l_dnaaCreateFull()
73
 *          l_int32      l_dnaaTruncate()
74
 *          void        *l_dnaaDestroy()
75
 *
76
 *      Add Dna to Dnaa
77
 *          l_int32      l_dnaaAddDna()
78
 *          static l_int32  l_dnaaExtendArray()
79
 *
80
 *      Dnaa accessors
81
 *          l_int32      l_dnaaGetCount()
82
 *          l_int32      l_dnaaGetDnaCount()
83
 *          l_int32      l_dnaaGetNumberCount()
84
 *          L_DNA       *l_dnaaGetDna()
85
 *          L_DNA       *l_dnaaReplaceDna()
86
 *          l_int32      l_dnaaGetValue()
87
 *          l_int32      l_dnaaAddNumber()
88
 *
89
 *      Serialize Dnaa for I/O
90
 *          L_DNAA      *l_dnaaRead()
91
 *          L_DNAA      *l_dnaaReadStream()
92
 *          L_DNAA      *l_dnaaReadMem()
93
 *          l_int32      l_dnaaWrite()
94
 *          l_int32      l_dnaaWriteStream()
95
 *          l_int32      l_dnaaWriteMem()
96
 *
97
 *    (1) The Dna is a struct holding an array of doubles.  It can also
98
 *        be used to store l_int32 values, up to the full precision
99
 *        of int32.  Always use it whenever integers larger than a
100
 *        few million need to be stored.
101
 *
102
 *    (2) Always use the accessors in this file, never the fields directly.
103
 *
104
 *    (3) Storing and retrieving numbers:
105
 *
106
 *       * to append a new number to the array, use l_dnaAddNumber().  If
107
 *         the number is an int, it will will automatically be converted
108
 *         to l_float64 and stored.
109
 *
110
 *       * to reset a value stored in the array, use l_dnaSetValue().
111
 *
112
 *       * to increment or decrement a value stored in the array,
113
 *         use l_dnaShiftValue().
114
 *
115
 *       * to obtain a value from the array, use either l_dnaGetIValue()
116
 *         or l_dnaGetDValue(), depending on whether you are retrieving
117
 *         an integer or a float64.  This avoids doing an explicit cast,
118
 *         such as
119
 *           (a) return a l_float64 and cast it to an l_int32
120
 *           (b) cast the return directly to (l_float64 *) to
121
 *               satisfy the function prototype, as in
122
 *                 l_dnaGetDValue(da, index, (l_float64 *)&ival);   [ugly!]
123
 *
124
 *    (4) int <--> double conversions:
125
 *
126
 *        Conversions go automatically from l_int32 --> l_float64,
127
 *        without loss of precision.  You must cast (l_int32)
128
 *        to go from l_float64 --> l_int32 because you're truncating
129
 *        to the integer value.
130
 *
131
 *    (5) As with other arrays in leptonica, the l_dna has both an allocated
132
 *        size and a count of the stored numbers.  When you add a number, it
133
 *        goes on the end of the array, and causes a realloc if the array
134
 *        is already filled.  However, in situations where you want to
135
 *        add numbers randomly into an array, such as when you build a
136
 *        histogram, you must set the count of stored numbers in advance.
137
 *        This is done with l_dnaSetCount().  If you set a count larger
138
 *        than the allocated array, it does a realloc to the size requested.
139
 *
140
 *    (6) In situations where the data in a l_dna correspond to a function
141
 *        y(x), the values can be either at equal spacings in x or at
142
 *        arbitrary spacings.  For the former, we can represent all x values
143
 *        by two parameters: startx (corresponding to y[0]) and delx
144
 *        for the change in x for adjacent values y[i] and y[i+1].
145
 *        startx and delx are initialized to 0.0 and 1.0, rsp.
146
 *        For arbitrary spacings, we use a second l_dna, and the two
147
 *        l_dnas are typically denoted dnay and dnax.
148
 * </pre>
149
 */
150
151
#ifdef HAVE_CONFIG_H
152
#include <config_auto.h>
153
#endif  /* HAVE_CONFIG_H */
154
155
#include <string.h>
156
#include <math.h>
157
#include "allheaders.h"
158
#include "array_internal.h"
159
160
    /* Bounds on initial array size */
161
static const l_uint32  MaxDoubleArraySize = 100000000;   /* for dna */
162
static const l_uint32  MaxPtrArraySize = 1000000;   /* for dnaa */
163
static const l_int32  InitialArraySize = 50;      /*!< n'importe quoi */
164
165
    /* Static functions */
166
static l_int32 l_dnaExtendArray(L_DNA *da);
167
static l_int32 l_dnaaExtendArray(L_DNAA *daa);
168
169
/*--------------------------------------------------------------------------*
170
 *                 Dna creation, destruction, copy, clone, etc.             *
171
 *--------------------------------------------------------------------------*/
172
/*!
173
 * \brief   l_dnaCreate()
174
 *
175
 * \param[in]    n   size of number array to be alloc'd; 0 for default
176
 * \return  da, or NULL on error
177
 */
178
L_DNA *
179
l_dnaCreate(l_int32  n)
180
0
{
181
0
L_DNA  *da;
182
183
0
    if (n <= 0 || n > MaxDoubleArraySize)
184
0
        n = InitialArraySize;
185
186
0
    da = (L_DNA *)LEPT_CALLOC(1, sizeof(L_DNA));
187
0
    if ((da->array = (l_float64 *)LEPT_CALLOC(n, sizeof(l_float64))) == NULL) {
188
0
        l_dnaDestroy(&da);
189
0
        return (L_DNA *)ERROR_PTR("double array not made", __func__, NULL);
190
0
    }
191
192
0
    da->nalloc = n;
193
0
    da->n = 0;
194
0
    da->refcount = 1;
195
0
    da->startx = 0.0;
196
0
    da->delx = 1.0;
197
198
0
    return da;
199
0
}
200
201
202
/*!
203
 * \brief   l_dnaCreateFromIArray()
204
 *
205
 * \param[in]    iarray   integer array
206
 * \param[in]    size     of the array
207
 * \return  da, or NULL on error
208
 *
209
 * <pre>
210
 * Notes:
211
 *      (1) We can't insert this int array into the l_dna, because a l_dna
212
 *          takes a double array.  So this just copies the data from the
213
 *          input array into the l_dna.  The input array continues to be
214
 *          owned by the caller.
215
 * </pre>
216
 */
217
L_DNA *
218
l_dnaCreateFromIArray(l_int32  *iarray,
219
                      l_int32   size)
220
0
{
221
0
l_int32  i;
222
0
L_DNA   *da;
223
224
0
    if (!iarray)
225
0
        return (L_DNA *)ERROR_PTR("iarray not defined", __func__, NULL);
226
0
    if (size <= 0)
227
0
        return (L_DNA *)ERROR_PTR("size must be > 0", __func__, NULL);
228
229
0
    da = l_dnaCreate(size);
230
0
    for (i = 0; i < size; i++)
231
0
        l_dnaAddNumber(da, iarray[i]);
232
233
0
    return da;
234
0
}
235
236
237
/*!
238
 * \brief   l_dnaCreateFromDArray()
239
 *
240
 * \param[in]    darray     float
241
 * \param[in]    size       of the array
242
 * \param[in]    copyflag   L_INSERT or L_COPY
243
 * \return  da, or NULL on error
244
 *
245
 * <pre>
246
 * Notes:
247
 *      (1) With L_INSERT, ownership of the input array is transferred
248
 *          to the returned l_dna, and all %size elements are considered
249
 *          to be valid.
250
 * </pre>
251
 */
252
L_DNA *
253
l_dnaCreateFromDArray(l_float64  *darray,
254
                      l_int32     size,
255
                      l_int32     copyflag)
256
0
{
257
0
l_int32  i;
258
0
L_DNA   *da;
259
260
0
    if (!darray)
261
0
        return (L_DNA *)ERROR_PTR("darray not defined", __func__, NULL);
262
0
    if (size <= 0)
263
0
        return (L_DNA *)ERROR_PTR("size must be > 0", __func__, NULL);
264
0
    if (copyflag != L_INSERT && copyflag != L_COPY)
265
0
        return (L_DNA *)ERROR_PTR("invalid copyflag", __func__, NULL);
266
267
0
    da = l_dnaCreate(size);
268
0
    if (copyflag == L_INSERT) {
269
0
        if (da->array) LEPT_FREE(da->array);
270
0
        da->array = darray;
271
0
        da->n = size;
272
0
    } else {  /* just copy the contents */
273
0
        for (i = 0; i < size; i++)
274
0
            l_dnaAddNumber(da, darray[i]);
275
0
    }
276
277
0
    return da;
278
0
}
279
280
281
/*!
282
 * \brief   l_dnaMakeSequence()
283
 *
284
 * \param[in]    startval
285
 * \param[in]    increment
286
 * \param[in]    size       of sequence
287
 * \return  l_dna of sequence of evenly spaced values, or NULL on error
288
 */
289
L_DNA *
290
l_dnaMakeSequence(l_float64  startval,
291
                  l_float64  increment,
292
                  l_int32    size)
293
0
{
294
0
l_int32    i;
295
0
l_float64  val;
296
0
L_DNA     *da;
297
298
0
    if ((da = l_dnaCreate(size)) == NULL)
299
0
        return (L_DNA *)ERROR_PTR("da not made", __func__, NULL);
300
301
0
    for (i = 0; i < size; i++) {
302
0
        val = startval + i * increment;
303
0
        l_dnaAddNumber(da, val);
304
0
    }
305
306
0
    return da;
307
0
}
308
309
310
/*!
311
 * \brief   l_dnaDestroy()
312
 *
313
 * \param[in,out]   pda   will be set to null before returning
314
 * \return  void
315
 *
316
 * <pre>
317
 * Notes:
318
 *      (1) Decrements the ref count and, if 0, destroys the l_dna.
319
 *      (2) Always nulls the input ptr.
320
 * </pre>
321
 */
322
void
323
l_dnaDestroy(L_DNA  **pda)
324
0
{
325
0
L_DNA  *da;
326
327
0
    if (pda == NULL) {
328
0
        L_WARNING("ptr address is NULL\n", __func__);
329
0
        return;
330
0
    }
331
332
0
    if ((da = *pda) == NULL)
333
0
        return;
334
335
        /* Decrement the ref count.  If it is 0, destroy the l_dna. */
336
0
    if (--da->refcount == 0) {
337
0
        if (da->array)
338
0
            LEPT_FREE(da->array);
339
0
        LEPT_FREE(da);
340
0
    }
341
0
    *pda = NULL;
342
0
}
343
344
345
/*!
346
 * \brief   l_dnaCopy()
347
 *
348
 * \param[in]    da
349
 * \return  copy of da, or NULL on error
350
 *
351
 * <pre>
352
 * Notes:
353
 *      (1) This removes unused ptrs above da->n.
354
 * </pre>
355
 */
356
L_DNA *
357
l_dnaCopy(L_DNA  *da)
358
0
{
359
0
l_int32  i;
360
0
L_DNA   *dac;
361
362
0
    if (!da)
363
0
        return (L_DNA *)ERROR_PTR("da not defined", __func__, NULL);
364
365
0
    if ((dac = l_dnaCreate(da->n)) == NULL)
366
0
        return (L_DNA *)ERROR_PTR("dac not made", __func__, NULL);
367
0
    dac->startx = da->startx;
368
0
    dac->delx = da->delx;
369
370
0
    for (i = 0; i < da->n; i++)
371
0
        l_dnaAddNumber(dac, da->array[i]);
372
373
0
    return dac;
374
0
}
375
376
377
/*!
378
 * \brief   l_dnaClone()
379
 *
380
 * \param[in]    da
381
 * \return  ptr to same da, or NULL on error
382
 */
383
L_DNA *
384
l_dnaClone(L_DNA  *da)
385
0
{
386
0
    if (!da)
387
0
        return (L_DNA *)ERROR_PTR("da not defined", __func__, NULL);
388
389
0
    ++da->refcount;
390
0
    return da;
391
0
}
392
393
394
/*!
395
 * \brief   l_dnaEmpty()
396
 *
397
 * \param[in]    da
398
 * \return  0 if OK; 1 on error
399
 *
400
 * <pre>
401
 * Notes:
402
 *      (1) This does not change the allocation of the array.
403
 *          It just clears the number of stored numbers, so that
404
 *          the array appears to be empty.
405
 * </pre>
406
 */
407
l_ok
408
l_dnaEmpty(L_DNA  *da)
409
0
{
410
0
    if (!da)
411
0
        return ERROR_INT("da not defined", __func__, 1);
412
413
0
    da->n = 0;
414
0
    return 0;
415
0
}
416
417
418
419
/*--------------------------------------------------------------------------*
420
 *                  Dna: add/remove number and extend array                 *
421
 *--------------------------------------------------------------------------*/
422
/*!
423
 * \brief   l_dnaAddNumber()
424
 *
425
 * \param[in]    da
426
 * \param[in]    val   float or int to be added; stored as a float
427
 * \return  0 if OK, 1 on error
428
 */
429
l_ok
430
l_dnaAddNumber(L_DNA     *da,
431
               l_float64  val)
432
0
{
433
0
l_int32  n;
434
435
0
    if (!da)
436
0
        return ERROR_INT("da not defined", __func__, 1);
437
438
0
    n = l_dnaGetCount(da);
439
0
    if (n >= da->nalloc) {
440
0
        if (l_dnaExtendArray(da))
441
0
            return ERROR_INT("extension failed", __func__, 1);
442
0
    }
443
0
    da->array[n] = val;
444
0
    da->n++;
445
0
    return 0;
446
0
}
447
448
449
/*!
450
 * \brief   l_dnaExtendArray()
451
 *
452
 * \param[in]    da
453
 * \return  0 if OK, 1 on error
454
 *
455
 * <pre>
456
 * Notes:
457
 *      (1) Doubles the size of the array.
458
 *      (2) The max number of doubles is 100M.
459
 * </pre>
460
 */
461
static l_int32
462
l_dnaExtendArray(L_DNA  *da)
463
0
{
464
0
size_t  oldsize, newsize;
465
466
0
    if (!da)
467
0
        return ERROR_INT("da not defined", __func__, 1);
468
0
    if (da->nalloc > MaxDoubleArraySize)
469
0
        return ERROR_INT("da at maximum size; can't extend", __func__, 1);
470
0
    oldsize = da->nalloc * sizeof(l_float64);
471
0
    if (da->nalloc > MaxDoubleArraySize / 2) {
472
0
        newsize = MaxDoubleArraySize * sizeof(l_float64);
473
0
        da->nalloc = MaxDoubleArraySize;
474
0
    } else {
475
0
        newsize = 2 * oldsize;
476
0
        da->nalloc *= 2;
477
0
    }
478
0
    if ((da->array = (l_float64 *)reallocNew((void **)&da->array,
479
0
                                             oldsize, newsize)) == NULL)
480
0
        return ERROR_INT("new ptr array not returned", __func__, 1);
481
482
0
    return 0;
483
0
}
484
485
486
/*!
487
 * \brief   l_dnaInsertNumber()
488
 *
489
 * \param[in]    da
490
 * \param[in]    index   location in da to insert new value
491
 * \param[in]    val     float64 or integer to be added
492
 * \return  0 if OK, 1 on error
493
 *
494
 * <pre>
495
 * Notes:
496
 *      (1) This shifts da[i] --> da[i + 1] for all i >= %index,
497
 *          and then inserts %val as da[%index].
498
 *      (2) It should not be used repeatedly on large arrays,
499
 *          because the function is O(n).
500
 *
501
 * </pre>
502
 */
503
l_ok
504
l_dnaInsertNumber(L_DNA      *da,
505
                  l_int32    index,
506
                  l_float64  val)
507
0
{
508
0
l_int32  i, n;
509
510
0
    if (!da)
511
0
        return ERROR_INT("da not defined", __func__, 1);
512
0
    n = l_dnaGetCount(da);
513
0
    if (index < 0 || index > n) {
514
0
        L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
515
0
        return 1;
516
0
    }
517
518
0
    if (n >= da->nalloc) {
519
0
        if (l_dnaExtendArray(da))
520
0
            return ERROR_INT("extension failed", __func__, 1);
521
0
    }
522
0
    for (i = n; i > index; i--)
523
0
        da->array[i] = da->array[i - 1];
524
0
    da->array[index] = val;
525
0
    da->n++;
526
0
    return 0;
527
0
}
528
529
530
/*!
531
 * \brief   l_dnaRemoveNumber()
532
 *
533
 * \param[in]    da
534
 * \param[in]    index    element to be removed
535
 * \return  0 if OK, 1 on error
536
 *
537
 * <pre>
538
 * Notes:
539
 *      (1) This shifts da[i] --> da[i - 1] for all i > %index.
540
 *      (2) It should not be used repeatedly on large arrays,
541
 *          because the function is O(n).
542
 * </pre>
543
 */
544
l_ok
545
l_dnaRemoveNumber(L_DNA   *da,
546
                  l_int32  index)
547
0
{
548
0
l_int32  i, n;
549
550
0
    if (!da)
551
0
        return ERROR_INT("da not defined", __func__, 1);
552
0
    n = l_dnaGetCount(da);
553
0
    if (index < 0 || index >= n) {
554
0
        L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
555
0
        return 1;
556
0
    }
557
558
0
    for (i = index + 1; i < n; i++)
559
0
        da->array[i - 1] = da->array[i];
560
0
    da->n--;
561
0
    return 0;
562
0
}
563
564
565
/*!
566
 * \brief   l_dnaReplaceNumber()
567
 *
568
 * \param[in]    da
569
 * \param[in]    index    element to be replaced
570
 * \param[in]    val      new value to replace old one
571
 * \return  0 if OK, 1 on error
572
 */
573
l_ok
574
l_dnaReplaceNumber(L_DNA     *da,
575
                   l_int32    index,
576
                   l_float64  val)
577
0
{
578
0
l_int32  n;
579
580
0
    if (!da)
581
0
        return ERROR_INT("da not defined", __func__, 1);
582
0
    n = l_dnaGetCount(da);
583
0
    if (index < 0 || index >= n) {
584
0
        L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
585
0
        return 1;
586
0
    }
587
588
0
    da->array[index] = val;
589
0
    return 0;
590
0
}
591
592
593
/*----------------------------------------------------------------------*
594
 *                             Dna accessors                            *
595
 *----------------------------------------------------------------------*/
596
/*!
597
 * \brief   l_dnaGetCount()
598
 *
599
 * \param[in]    da
600
 * \return  count, or 0 if no numbers or on error
601
 */
602
l_int32
603
l_dnaGetCount(L_DNA  *da)
604
0
{
605
0
    if (!da)
606
0
        return ERROR_INT("da not defined", __func__, 0);
607
0
    return da->n;
608
0
}
609
610
611
/*!
612
 * \brief   l_dnaSetCount()
613
 *
614
 * \param[in]    da
615
 * \param[in]    newcount
616
 * \return  0 if OK, 1 on error
617
 *
618
 * <pre>
619
 * Notes:
620
 *      (1) If %newcount <= da->nalloc, this resets da->n.
621
 *          Using %newcount = 0 is equivalent to l_dnaEmpty().
622
 *      (2) If %newcount > da->nalloc, this causes a realloc
623
 *          to a size da->nalloc = %newcount.
624
 *      (3) All the previously unused values in da are set to 0.0.
625
 * </pre>
626
 */
627
l_ok
628
l_dnaSetCount(L_DNA   *da,
629
              l_int32  newcount)
630
0
{
631
0
    if (!da)
632
0
        return ERROR_INT("da not defined", __func__, 1);
633
0
    if (newcount > da->nalloc) {
634
0
        if ((da->array = (l_float64 *)reallocNew((void **)&da->array,
635
0
                         sizeof(l_float64) * da->nalloc,
636
0
                         sizeof(l_float64) * newcount)) == NULL)
637
0
            return ERROR_INT("new ptr array not returned", __func__, 1);
638
0
        da->nalloc = newcount;
639
0
    }
640
0
    da->n = newcount;
641
0
    return 0;
642
0
}
643
644
645
/*!
646
 * \brief   l_dnaGetDValue()
647
 *
648
 * \param[in]    da
649
 * \param[in]    index    into l_dna
650
 * \param[out]   pval     double value; 0.0 on error
651
 * \return  0 if OK; 1 on error
652
 *
653
 * <pre>
654
 * Notes:
655
 *      (1) Caller may need to check the function return value to
656
 *          decide if a 0.0 in the returned ival is valid.
657
 * </pre>
658
 */
659
l_ok
660
l_dnaGetDValue(L_DNA      *da,
661
               l_int32     index,
662
               l_float64  *pval)
663
0
{
664
0
    if (!pval)
665
0
        return ERROR_INT("&val not defined", __func__, 1);
666
0
    *pval = 0.0;
667
0
    if (!da)
668
0
        return ERROR_INT("da not defined", __func__, 1);
669
670
0
    if (index < 0 || index >= da->n)
671
0
        return ERROR_INT("index not valid", __func__, 1);
672
673
0
    *pval = da->array[index];
674
0
    return 0;
675
0
}
676
677
678
/*!
679
 * \brief   l_dnaGetIValue()
680
 *
681
 * \param[in]    da
682
 * \param[in]    index    into l_dna
683
 * \param[out]   pival    integer value; 0 on error
684
 * \return  0 if OK; 1 on error
685
 *
686
 * <pre>
687
 * Notes:
688
 *      (1) Caller may need to check the function return value to
689
 *          decide if a 0 in the returned ival is valid.
690
 * </pre>
691
 */
692
l_ok
693
l_dnaGetIValue(L_DNA    *da,
694
               l_int32   index,
695
               l_int32  *pival)
696
0
{
697
0
l_float64  val;
698
699
0
    if (!pival)
700
0
        return ERROR_INT("&ival not defined", __func__, 1);
701
0
    *pival = 0;
702
0
    if (!da)
703
0
        return ERROR_INT("da not defined", __func__, 1);
704
705
0
    if (index < 0 || index >= da->n)
706
0
        return ERROR_INT("index not valid", __func__, 1);
707
708
0
    val = da->array[index];
709
0
    *pival = (l_int32)(val + L_SIGN(val) * 0.5);
710
0
    return 0;
711
0
}
712
713
714
/*!
715
 * \brief   l_dnaSetValue()
716
 *
717
 * \param[in]    da
718
 * \param[in]    index    to element to be set
719
 * \param[in]    val      to set element
720
 * \return  0 if OK; 1 on error
721
 */
722
l_ok
723
l_dnaSetValue(L_DNA     *da,
724
              l_int32    index,
725
              l_float64  val)
726
0
{
727
0
    if (!da)
728
0
        return ERROR_INT("da not defined", __func__, 1);
729
0
    if (index < 0 || index >= da->n)
730
0
        return ERROR_INT("index not valid", __func__, 1);
731
732
0
    da->array[index] = val;
733
0
    return 0;
734
0
}
735
736
737
/*!
738
 * \brief   l_dnaShiftValue()
739
 *
740
 * \param[in]    da
741
 * \param[in]    index   to element to change relative to the current value
742
 * \param[in]    diff    increment if diff > 0 or decrement if diff < 0
743
 * \return  0 if OK; 1 on error
744
 */
745
l_ok
746
l_dnaShiftValue(L_DNA     *da,
747
                l_int32    index,
748
                l_float64  diff)
749
0
{
750
0
    if (!da)
751
0
        return ERROR_INT("da not defined", __func__, 1);
752
0
    if (index < 0 || index >= da->n)
753
0
        return ERROR_INT("index not valid", __func__, 1);
754
755
0
    da->array[index] += diff;
756
0
    return 0;
757
0
}
758
759
760
/*!
761
 * \brief   l_dnaGetIArray()
762
 *
763
 * \param[in]    da
764
 * \return  a copy of the bare internal array, integerized
765
 *              by rounding, or NULL on error
766
 * <pre>
767
 * Notes:
768
 *      (1) A copy of the array is made, because we need to
769
 *          generate an integer array from the bare double array.
770
 *          The caller is responsible for freeing the array.
771
 *      (2) The array size is determined by the number of stored numbers,
772
 *          not by the size of the allocated array in the l_dna.
773
 *      (3) This function is provided to simplify calculations
774
 *          using the bare internal array, rather than continually
775
 *          calling accessors on the l_dna.  It is typically used
776
 *          on an array of size 256.
777
 * </pre>
778
 */
779
l_int32 *
780
l_dnaGetIArray(L_DNA  *da)
781
0
{
782
0
l_int32   i, n, ival;
783
0
l_int32  *array;
784
785
0
    if (!da)
786
0
        return (l_int32 *)ERROR_PTR("da not defined", __func__, NULL);
787
788
0
    n = l_dnaGetCount(da);
789
0
    if ((array = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
790
0
        return (l_int32 *)ERROR_PTR("array not made", __func__, NULL);
791
0
    for (i = 0; i < n; i++) {
792
0
        l_dnaGetIValue(da, i, &ival);
793
0
        array[i] = ival;
794
0
    }
795
796
0
    return array;
797
0
}
798
799
800
/*!
801
 * \brief   l_dnaGetDArray()
802
 *
803
 * \param[in]    da
804
 * \param[in]    copyflag   L_NOCOPY or L_COPY
805
 * \return  either the bare internal array or a copy of it, or NULL on error
806
 *
807
 * <pre>
808
 * Notes:
809
 *      (1) If %copyflag == L_COPY, it makes a copy which the caller
810
 *          is responsible for freeing.  Otherwise, it operates
811
 *          directly on the bare array of the l_dna.
812
 *      (2) Very important: for L_NOCOPY, any writes to the array
813
 *          will be in the l_dna.  Do not write beyond the size of
814
 *          the count field, because it will not be accessible
815
 *          from the l_dna!  If necessary, be sure to set the count
816
 *          field to a larger number (such as the alloc size)
817
 *          BEFORE calling this function.  Creating with l_dnaMakeConstant()
818
 *          is another way to insure full initialization.
819
 * </pre>
820
 */
821
l_float64 *
822
l_dnaGetDArray(L_DNA   *da,
823
               l_int32  copyflag)
824
0
{
825
0
l_int32     i, n;
826
0
l_float64  *array;
827
828
0
    if (!da)
829
0
        return (l_float64 *)ERROR_PTR("da not defined", __func__, NULL);
830
831
0
    if (copyflag == L_NOCOPY) {
832
0
        array = da->array;
833
0
    } else {  /* copyflag == L_COPY */
834
0
        n = l_dnaGetCount(da);
835
0
        if ((array = (l_float64 *)LEPT_CALLOC(n, sizeof(l_float64))) == NULL)
836
0
            return (l_float64 *)ERROR_PTR("array not made", __func__, NULL);
837
0
        for (i = 0; i < n; i++)
838
0
            array[i] = da->array[i];
839
0
    }
840
841
0
    return array;
842
0
}
843
844
845
/*!
846
 * \brief   l_dnaGetParameters()
847
 *
848
 * \param[in]    da
849
 * \param[out]   pstartx   [optional] startx
850
 * \param[out]   pdelx     [optional] delx
851
 * \return  0 if OK, 1 on error
852
 */
853
l_ok
854
l_dnaGetParameters(L_DNA     *da,
855
                   l_float64  *pstartx,
856
                   l_float64  *pdelx)
857
0
{
858
0
    if (pstartx) *pstartx = 0.0;
859
0
    if (pdelx) *pdelx = 1.0;
860
0
    if (!pstartx && !pdelx)
861
0
        return ERROR_INT("neither &startx nor &delx are defined", __func__, 1);
862
0
    if (!da)
863
0
        return ERROR_INT("da not defined", __func__, 1);
864
865
0
    if (pstartx) *pstartx = da->startx;
866
0
    if (pdelx) *pdelx = da->delx;
867
0
    return 0;
868
0
}
869
870
871
/*!
872
 * \brief   l_dnaSetParameters()
873
 *
874
 * \param[in]    da
875
 * \param[in]    startx   x value corresponding to da[0]
876
 * \param[in]    delx     difference in x values for the situation where the
877
 *                        elements of da correspond to the evaluation of a
878
 *                        function at equal intervals of size %delx
879
 * \return  0 if OK, 1 on error
880
 */
881
l_ok
882
l_dnaSetParameters(L_DNA     *da,
883
                   l_float64  startx,
884
                   l_float64  delx)
885
0
{
886
0
    if (!da)
887
0
        return ERROR_INT("da not defined", __func__, 1);
888
889
0
    da->startx = startx;
890
0
    da->delx = delx;
891
0
    return 0;
892
0
}
893
894
895
/*!
896
 * \brief   l_dnaCopyParameters()
897
 *
898
 * \param[in]    dad    destination DNuma
899
 * \param[in]    das    source DNuma
900
 * \return  0 if OK, 1 on error
901
 */
902
l_ok
903
l_dnaCopyParameters(L_DNA  *dad,
904
                    L_DNA  *das)
905
0
{
906
0
l_float64  start, binsize;
907
908
0
    if (!das || !dad)
909
0
        return ERROR_INT("das and dad not both defined", __func__, 1);
910
911
0
    l_dnaGetParameters(das, &start, &binsize);
912
0
    l_dnaSetParameters(dad, start, binsize);
913
0
    return 0;
914
0
}
915
916
917
/*----------------------------------------------------------------------*
918
 *                        Serialize Dna for I/O                         *
919
 *----------------------------------------------------------------------*/
920
/*!
921
 * \brief   l_dnaRead()
922
 *
923
 * \param[in]    filename
924
 * \return  da, or NULL on error
925
 */
926
L_DNA *
927
l_dnaRead(const char  *filename)
928
0
{
929
0
FILE   *fp;
930
0
L_DNA  *da;
931
932
0
    if (!filename)
933
0
        return (L_DNA *)ERROR_PTR("filename not defined", __func__, NULL);
934
935
0
    if ((fp = fopenReadStream(filename)) == NULL)
936
0
        return (L_DNA *)ERROR_PTR_1("stream not opened",
937
0
                                    filename, __func__, NULL);
938
0
    da = l_dnaReadStream(fp);
939
0
    fclose(fp);
940
0
    if (!da)
941
0
        return (L_DNA *)ERROR_PTR_1("da not read",
942
0
                                    filename, __func__, NULL);
943
0
    return da;
944
0
}
945
946
947
/*!
948
 * \brief   l_dnaReadStream()
949
 *
950
 * \param[in]    fp    file stream
951
 * \return  da, or NULL on error
952
 *
953
 * <pre>
954
 * Notes:
955
 *      (1) fscanf takes %lf to read a double; fprintf takes %f to write it.
956
 *      (2) It is OK for the dna to be empty.
957
 * </pre>
958
 */
959
L_DNA *
960
l_dnaReadStream(FILE  *fp)
961
0
{
962
0
l_int32    i, n, index, ret, version;
963
0
l_float64  val, startx, delx;
964
0
L_DNA     *da;
965
966
0
    if (!fp)
967
0
        return (L_DNA *)ERROR_PTR("stream not defined", __func__, NULL);
968
969
0
    ret = fscanf(fp, "\nL_Dna Version %d\n", &version);
970
0
    if (ret != 1)
971
0
        return (L_DNA *)ERROR_PTR("not a l_dna file", __func__, NULL);
972
0
    if (version != DNA_VERSION_NUMBER)
973
0
        return (L_DNA *)ERROR_PTR("invalid l_dna version", __func__, NULL);
974
0
    if (fscanf(fp, "Number of numbers = %d\n", &n) != 1)
975
0
        return (L_DNA *)ERROR_PTR("invalid number of numbers", __func__, NULL);
976
0
    if (n < 0)
977
0
        return (L_DNA *)ERROR_PTR("num doubles < 0", __func__, NULL);
978
0
    if (n > MaxDoubleArraySize)
979
0
        return (L_DNA *)ERROR_PTR("too many doubles", __func__, NULL);
980
0
    if (n == 0) L_INFO("the dna is empty\n", __func__);
981
982
0
    if ((da = l_dnaCreate(n)) == NULL)
983
0
        return (L_DNA *)ERROR_PTR("da not made", __func__, NULL);
984
0
    for (i = 0; i < n; i++) {
985
0
        if (fscanf(fp, "  [%d] = %lf\n", &index, &val) != 2) {
986
0
            l_dnaDestroy(&da);
987
0
            return (L_DNA *)ERROR_PTR("bad input data", __func__, NULL);
988
0
        }
989
0
        l_dnaAddNumber(da, val);
990
0
    }
991
992
        /* Optional data */
993
0
    if (fscanf(fp, "startx = %lf, delx = %lf\n", &startx, &delx) == 2)
994
0
        l_dnaSetParameters(da, startx, delx);
995
0
    return da;
996
0
}
997
998
999
/*!
1000
 * \brief   l_dnaReadMem()
1001
 *
1002
 * \param[in]    data    dna serialization; in ascii
1003
 * \param[in]    size    of data; can use strlen to get it
1004
 * \return  da, or NULL on error
1005
 */
1006
L_DNA *
1007
l_dnaReadMem(const l_uint8  *data,
1008
             size_t          size)
1009
0
{
1010
0
FILE   *fp;
1011
0
L_DNA  *da;
1012
1013
0
    if (!data)
1014
0
        return (L_DNA *)ERROR_PTR("data not defined", __func__, NULL);
1015
0
    if ((fp = fopenReadFromMemory(data, size)) == NULL)
1016
0
        return (L_DNA *)ERROR_PTR("stream not opened", __func__, NULL);
1017
1018
0
    da = l_dnaReadStream(fp);
1019
0
    fclose(fp);
1020
0
    if (!da) L_ERROR("dna not read\n", __func__);
1021
0
    return da;
1022
0
}
1023
1024
1025
/*!
1026
 * \brief   l_dnaWrite()
1027
 *
1028
 * \param[in]    filename
1029
 * \param[in]    da
1030
 * \return  0 if OK, 1 on error
1031
 */
1032
l_ok
1033
l_dnaWrite(const char  *filename,
1034
           L_DNA       *da)
1035
0
{
1036
0
l_int32  ret;
1037
0
FILE    *fp;
1038
1039
0
    if (!filename)
1040
0
        return ERROR_INT("filename not defined", __func__, 1);
1041
0
    if (!da)
1042
0
        return ERROR_INT("da not defined", __func__, 1);
1043
1044
0
    if ((fp = fopenWriteStream(filename, "w")) == NULL)
1045
0
        return ERROR_INT_1("stream not opened", filename, __func__, 1);
1046
0
    ret = l_dnaWriteStream(fp, da);
1047
0
    fclose(fp);
1048
0
    if (ret)
1049
0
        return ERROR_INT_1("da not written to stream", filename, __func__, 1);
1050
0
    return 0;
1051
0
}
1052
1053
1054
/*!
1055
 * \brief   l_dnaWriteStream()
1056
 *
1057
 * \param[in]    fp    file stream; use NULL to write to stderr
1058
 * \param[in]    da
1059
 * \return  0 if OK, 1 on error
1060
 */
1061
l_ok
1062
l_dnaWriteStream(FILE   *fp,
1063
                 L_DNA  *da)
1064
0
{
1065
0
l_int32    i, n;
1066
0
l_float64  startx, delx;
1067
1068
0
    if (!da)
1069
0
        return ERROR_INT("da not defined", __func__, 1);
1070
0
    if (!fp)
1071
0
        return l_dnaWriteStderr(da);
1072
1073
0
    n = l_dnaGetCount(da);
1074
0
    fprintf(fp, "\nL_Dna Version %d\n", DNA_VERSION_NUMBER);
1075
0
    fprintf(fp, "Number of numbers = %d\n", n);
1076
0
    for (i = 0; i < n; i++)
1077
0
        fprintf(fp, "  [%d] = %f\n", i, da->array[i]);
1078
0
    fprintf(fp, "\n");
1079
1080
        /* Optional data */
1081
0
    l_dnaGetParameters(da, &startx, &delx);
1082
0
    if (startx != 0.0 || delx != 1.0)
1083
0
        fprintf(fp, "startx = %f, delx = %f\n", startx, delx);
1084
1085
0
    return 0;
1086
0
}
1087
1088
1089
/*!
1090
 * \brief   l_dnaWriteStrderr()
1091
 *
1092
 * \param[in]    da
1093
 * \return  0 if OK, 1 on error
1094
 */
1095
l_ok
1096
l_dnaWriteStderr(L_DNA  *da)
1097
0
{
1098
0
l_int32    i, n;
1099
0
l_float64  startx, delx;
1100
1101
0
    if (!da)
1102
0
        return ERROR_INT("da not defined", __func__, 1);
1103
1104
0
    n = l_dnaGetCount(da);
1105
0
    lept_stderr("\nL_Dna Version %d\n", DNA_VERSION_NUMBER);
1106
0
    lept_stderr("Number of numbers = %d\n", n);
1107
0
    for (i = 0; i < n; i++)
1108
0
        lept_stderr("  [%d] = %f\n", i, da->array[i]);
1109
0
    lept_stderr("\n");
1110
1111
        /* Optional data */
1112
0
    l_dnaGetParameters(da, &startx, &delx);
1113
0
    if (startx != 0.0 || delx != 1.0)
1114
0
        lept_stderr("startx = %f, delx = %f\n", startx, delx);
1115
1116
0
    return 0;
1117
0
}
1118
1119
1120
/*!
1121
 * \brief   l_dnaWriteMem()
1122
 *
1123
 * \param[out]   pdata    data of serialized dna; ascii
1124
 * \param[out]   psize    size of returned data
1125
 * \param[in]    da
1126
 * \return  0 if OK, 1 on error
1127
 *
1128
 * <pre>
1129
 * Notes:
1130
 *      (1) Serializes a dna in memory and puts the result in a buffer.
1131
 * </pre>
1132
 */
1133
l_ok
1134
l_dnaWriteMem(l_uint8  **pdata,
1135
              size_t    *psize,
1136
              L_DNA     *da)
1137
0
{
1138
0
l_int32  ret;
1139
0
FILE    *fp;
1140
1141
0
    if (pdata) *pdata = NULL;
1142
0
    if (psize) *psize = 0;
1143
0
    if (!pdata)
1144
0
        return ERROR_INT("&data not defined", __func__, 1);
1145
0
    if (!psize)
1146
0
        return ERROR_INT("&size not defined", __func__, 1);
1147
0
    if (!da)
1148
0
        return ERROR_INT("da not defined", __func__, 1);
1149
1150
0
#if HAVE_FMEMOPEN
1151
0
    if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1152
0
        return ERROR_INT("stream not opened", __func__, 1);
1153
0
    ret = l_dnaWriteStream(fp, da);
1154
0
    fputc('\0', fp);
1155
0
    fclose(fp);
1156
0
    if (*psize > 0) *psize = *psize - 1;
1157
#else
1158
    L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
1159
  #ifdef _WIN32
1160
    if ((fp = fopenWriteWinTempfile()) == NULL)
1161
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
1162
  #else
1163
    if ((fp = tmpfile()) == NULL)
1164
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
1165
  #endif  /* _WIN32 */
1166
    ret = l_dnaWriteStream(fp, da);
1167
    rewind(fp);
1168
    *pdata = l_binaryReadStream(fp, psize);
1169
    fclose(fp);
1170
#endif  /* HAVE_FMEMOPEN */
1171
0
    return ret;
1172
0
}
1173
1174
1175
/*--------------------------------------------------------------------------*
1176
 *                       Dnaa creation, destruction                         *
1177
 *--------------------------------------------------------------------------*/
1178
/*!
1179
 * \brief   l_dnaaCreate()
1180
 *
1181
 * \param[in]    n    size of l_dna ptr array to be alloc'd 0 for default
1182
 * \return  daa, or NULL on error
1183
 *
1184
 */
1185
L_DNAA *
1186
l_dnaaCreate(l_int32  n)
1187
0
{
1188
0
L_DNAA  *daa;
1189
1190
0
    if (n <= 0 || n > MaxPtrArraySize)
1191
0
        n = InitialArraySize;
1192
1193
0
    daa = (L_DNAA *)LEPT_CALLOC(1, sizeof(L_DNAA));
1194
0
    if ((daa->dna = (L_DNA **)LEPT_CALLOC(n, sizeof(L_DNA *))) == NULL) {
1195
0
        l_dnaaDestroy(&daa);
1196
0
        return (L_DNAA *)ERROR_PTR("l_dna ptr array not made", __func__, NULL);
1197
0
    }
1198
0
    daa->nalloc = n;
1199
0
    daa->n = 0;
1200
0
    return daa;
1201
0
}
1202
1203
1204
/*!
1205
 * \brief   l_dnaaCreateFull()
1206
 *
1207
 * \param[in]    nptr  size of dna ptr array to be alloc'd
1208
 * \param[in]    n     size of individual dna arrays to be alloc'd 0 for default
1209
 * \return  daa, or NULL on error
1210
 *
1211
 * <pre>
1212
 * Notes:
1213
 *      (1) This allocates a dnaa and fills the array with allocated dnas.
1214
 *          In use, after calling this function, use
1215
 *              l_dnaaAddNumber(dnaa, index, val);
1216
 *          to add val to the index-th dna in dnaa.
1217
 * </pre>
1218
 */
1219
L_DNAA *
1220
l_dnaaCreateFull(l_int32  nptr,
1221
                 l_int32  n)
1222
0
{
1223
0
l_int32  i;
1224
0
L_DNAA  *daa;
1225
0
L_DNA   *da;
1226
1227
0
    daa = l_dnaaCreate(nptr);
1228
0
    for (i = 0; i < nptr; i++) {
1229
0
        da = l_dnaCreate(n);
1230
0
        l_dnaaAddDna(daa, da, L_INSERT);
1231
0
    }
1232
1233
0
    return daa;
1234
0
}
1235
1236
1237
/*!
1238
 * \brief   l_dnaaTruncate()
1239
 *
1240
 * \param[in]    daa
1241
 * \return  0 if OK, 1 on error
1242
 *
1243
 * <pre>
1244
 * Notes:
1245
 *      (1) This identifies the largest index containing a dna that
1246
 *          has any numbers within it, destroys all dna beyond that
1247
 *          index, and resets the count.
1248
 * </pre>
1249
 */
1250
l_ok
1251
l_dnaaTruncate(L_DNAA  *daa)
1252
0
{
1253
0
l_int32  i, n, nn;
1254
0
L_DNA   *da;
1255
1256
0
    if (!daa)
1257
0
        return ERROR_INT("daa not defined", __func__, 1);
1258
1259
0
    n = l_dnaaGetCount(daa);
1260
0
    for (i = n - 1; i >= 0; i--) {
1261
0
        da = l_dnaaGetDna(daa, i, L_CLONE);
1262
0
        if (!da)
1263
0
            continue;
1264
0
        nn = l_dnaGetCount(da);
1265
0
        l_dnaDestroy(&da);  /* the clone */
1266
0
        if (nn == 0)
1267
0
            l_dnaDestroy(&daa->dna[i]);
1268
0
        else
1269
0
            break;
1270
0
    }
1271
0
    daa->n = i + 1;
1272
0
    return 0;
1273
0
}
1274
1275
1276
/*!
1277
 * \brief   l_dnaaDestroy()
1278
 *
1279
 * \param[in,out]   pdaa    will be set to null before returning
1280
 * \return  void
1281
 */
1282
void
1283
l_dnaaDestroy(L_DNAA  **pdaa)
1284
0
{
1285
0
l_int32  i;
1286
0
L_DNAA  *daa;
1287
1288
0
    if (pdaa == NULL) {
1289
0
        L_WARNING("ptr address is NULL!\n", __func__);
1290
0
        return;
1291
0
    }
1292
1293
0
    if ((daa = *pdaa) == NULL)
1294
0
        return;
1295
1296
0
    for (i = 0; i < daa->n; i++)
1297
0
        l_dnaDestroy(&daa->dna[i]);
1298
0
    LEPT_FREE(daa->dna);
1299
0
    LEPT_FREE(daa);
1300
0
    *pdaa = NULL;
1301
0
}
1302
1303
1304
/*--------------------------------------------------------------------------*
1305
 *                             Add Dna to Dnaa                              *
1306
 *--------------------------------------------------------------------------*/
1307
/*!
1308
 * \brief   l_dnaaAddDna()
1309
 *
1310
 * \param[in]    daa
1311
 * \param[in]    da         to be added
1312
 * \param[in]    copyflag   L_INSERT, L_COPY, L_CLONE
1313
 * \return  0 if OK, 1 on error
1314
 */
1315
l_ok
1316
l_dnaaAddDna(L_DNAA  *daa,
1317
             L_DNA   *da,
1318
             l_int32  copyflag)
1319
0
{
1320
0
l_int32  n;
1321
0
L_DNA   *dac;
1322
1323
0
    if (!daa)
1324
0
        return ERROR_INT("daa not defined", __func__, 1);
1325
0
    if (!da)
1326
0
        return ERROR_INT("da not defined", __func__, 1);
1327
1328
0
    if (copyflag == L_INSERT) {
1329
0
        dac = da;
1330
0
    } else if (copyflag == L_COPY) {
1331
0
        if ((dac = l_dnaCopy(da)) == NULL)
1332
0
            return ERROR_INT("dac not made", __func__, 1);
1333
0
    } else if (copyflag == L_CLONE) {
1334
0
        dac = l_dnaClone(da);
1335
0
    } else {
1336
0
        return ERROR_INT("invalid copyflag", __func__, 1);
1337
0
    }
1338
1339
0
    n = l_dnaaGetCount(daa);
1340
0
    if (n >= daa->nalloc) {
1341
0
        if (l_dnaaExtendArray(daa)) {
1342
0
            if (copyflag != L_INSERT)
1343
0
                l_dnaDestroy(&dac);
1344
0
            return ERROR_INT("extension failed", __func__, 1);
1345
0
        }
1346
0
    }
1347
0
    daa->dna[n] = dac;
1348
0
    daa->n++;
1349
0
    return 0;
1350
0
}
1351
1352
1353
/*!
1354
 * \brief   l_dnaaExtendArray()
1355
 *
1356
 * \param[in]    daa
1357
 * \return  0 if OK, 1 on error
1358
 *
1359
 * <pre>
1360
 * Notes:
1361
 *      (1) Doubles the number of dna ptrs.
1362
 *      (2) The max size of the dna array is 1M ptrs.
1363
 * </pre>
1364
 */
1365
static l_int32
1366
l_dnaaExtendArray(L_DNAA  *daa)
1367
0
{
1368
0
size_t  oldsize, newsize;
1369
1370
0
    if (!daa)
1371
0
        return ERROR_INT("daa not defined", __func__, 1);
1372
0
    if (daa->nalloc > MaxPtrArraySize)  /* belt & suspenders */
1373
0
        return ERROR_INT("daa has too many ptrs", __func__, 1);
1374
0
    oldsize = daa->nalloc * sizeof(L_DNA *);
1375
0
    newsize = 2 * oldsize;
1376
0
    if (newsize > 8 * MaxPtrArraySize)
1377
0
        return ERROR_INT("newsize > 8 MB; too large", __func__, 1);
1378
1379
0
    if ((daa->dna = (L_DNA **)reallocNew((void **)&daa->dna,
1380
0
                                         oldsize, newsize)) == NULL)
1381
0
        return ERROR_INT("new ptr array not returned", __func__, 1);
1382
1383
0
    daa->nalloc *= 2;
1384
0
    return 0;
1385
0
}
1386
1387
1388
/*----------------------------------------------------------------------*
1389
 *                           DNumaa accessors                           *
1390
 *----------------------------------------------------------------------*/
1391
/*!
1392
 * \brief   l_dnaaGetCount()
1393
 *
1394
 * \param[in]    daa
1395
 * \return  count   number of l_dna, or 0 if no l_dna or on error
1396
 */
1397
l_int32
1398
l_dnaaGetCount(L_DNAA  *daa)
1399
0
{
1400
0
    if (!daa)
1401
0
        return ERROR_INT("daa not defined", __func__, 0);
1402
0
    return daa->n;
1403
0
}
1404
1405
1406
/*!
1407
 * \brief   l_dnaaGetDnaCount()
1408
 *
1409
 * \param[in]    daa
1410
 * \param[in]    index   of l_dna in daa
1411
 * \return  count   of numbers in the referenced l_dna, or 0 on error.
1412
 */
1413
l_int32
1414
l_dnaaGetDnaCount(L_DNAA   *daa,
1415
                    l_int32  index)
1416
0
{
1417
0
    if (!daa)
1418
0
        return ERROR_INT("daa not defined", __func__, 0);
1419
0
    if (index < 0 || index >= daa->n)
1420
0
        return ERROR_INT("invalid index into daa", __func__, 0);
1421
0
    return l_dnaGetCount(daa->dna[index]);
1422
0
}
1423
1424
1425
/*!
1426
 * \brief   l_dnaaGetNumberCount()
1427
 *
1428
 * \param[in]    daa
1429
 * \return  count   total number of numbers in the l_dnaa,
1430
 *                  or 0 if no numbers or on error
1431
 */
1432
l_int32
1433
l_dnaaGetNumberCount(L_DNAA  *daa)
1434
0
{
1435
0
L_DNA   *da;
1436
0
l_int32  n, sum, i;
1437
1438
0
    if (!daa)
1439
0
        return ERROR_INT("daa not defined", __func__, 0);
1440
1441
0
    n = l_dnaaGetCount(daa);
1442
0
    for (sum = 0, i = 0; i < n; i++) {
1443
0
        da = l_dnaaGetDna(daa, i, L_CLONE);
1444
0
        sum += l_dnaGetCount(da);
1445
0
        l_dnaDestroy(&da);
1446
0
    }
1447
1448
0
    return sum;
1449
0
}
1450
1451
1452
/*!
1453
 * \brief   l_dnaaGetDna()
1454
 *
1455
 * \param[in]    daa
1456
 * \param[in]    index        to the index-th l_dna
1457
 * \param[in]    accessflag   L_COPY or L_CLONE
1458
 * \return  l_dna, or NULL on error
1459
 */
1460
L_DNA *
1461
l_dnaaGetDna(L_DNAA  *daa,
1462
             l_int32  index,
1463
             l_int32  accessflag)
1464
0
{
1465
0
    if (!daa)
1466
0
        return (L_DNA *)ERROR_PTR("daa not defined", __func__, NULL);
1467
0
    if (index < 0 || index >= daa->n)
1468
0
        return (L_DNA *)ERROR_PTR("index not valid", __func__, NULL);
1469
1470
0
    if (accessflag == L_COPY)
1471
0
        return l_dnaCopy(daa->dna[index]);
1472
0
    else if (accessflag == L_CLONE)
1473
0
        return l_dnaClone(daa->dna[index]);
1474
0
    else
1475
0
        return (L_DNA *)ERROR_PTR("invalid accessflag", __func__, NULL);
1476
0
}
1477
1478
1479
/*!
1480
 * \brief   l_dnaaReplaceDna()
1481
 *
1482
 * \param[in]    daa
1483
 * \param[in]    index   to the index-th l_dna
1484
 * \param[in]    da      insert and replace any existing one
1485
 * \return  0 if OK, 1 on error
1486
 *
1487
 * <pre>
1488
 * Notes:
1489
 *      (1) Any existing l_dna is destroyed, and the input one
1490
 *          is inserted in its place.
1491
 *      (2) If %index is invalid, return 1 (error)
1492
 * </pre>
1493
 */
1494
l_ok
1495
l_dnaaReplaceDna(L_DNAA  *daa,
1496
                 l_int32  index,
1497
                 L_DNA   *da)
1498
0
{
1499
0
l_int32  n;
1500
1501
0
    if (!daa)
1502
0
        return ERROR_INT("daa not defined", __func__, 1);
1503
0
    if (!da)
1504
0
        return ERROR_INT("da not defined", __func__, 1);
1505
0
    n = l_dnaaGetCount(daa);
1506
0
    if (index < 0 || index >= n)
1507
0
        return ERROR_INT("index not valid", __func__, 1);
1508
1509
0
    l_dnaDestroy(&daa->dna[index]);
1510
0
    daa->dna[index] = da;
1511
0
    return 0;
1512
0
}
1513
1514
1515
/*!
1516
 * \brief   l_dnaaGetValue()
1517
 *
1518
 * \param[in]    daa
1519
 * \param[in]    i      index of l_dna within l_dnaa
1520
 * \param[in]    j      index into l_dna
1521
 * \param[out]   pval   double value
1522
 * \return  0 if OK, 1 on error
1523
 */
1524
l_ok
1525
l_dnaaGetValue(L_DNAA     *daa,
1526
               l_int32     i,
1527
               l_int32     j,
1528
               l_float64  *pval)
1529
0
{
1530
0
l_int32  n;
1531
0
L_DNA   *da;
1532
1533
0
    if (!pval)
1534
0
        return ERROR_INT("&val not defined", __func__, 1);
1535
0
    *pval = 0.0;
1536
0
    if (!daa)
1537
0
        return ERROR_INT("daa not defined", __func__, 1);
1538
0
    n = l_dnaaGetCount(daa);
1539
0
    if (i < 0 || i >= n)
1540
0
        return ERROR_INT("invalid index into daa", __func__, 1);
1541
0
    da = daa->dna[i];
1542
0
    if (j < 0 || j >= da->n)
1543
0
        return ERROR_INT("invalid index into da", __func__, 1);
1544
0
    *pval = da->array[j];
1545
0
    return 0;
1546
0
}
1547
1548
1549
/*!
1550
 * \brief   l_dnaaAddNumber()
1551
 *
1552
 * \param[in]    daa
1553
 * \param[in]    index    of l_dna within l_dnaa
1554
 * \param[in]    val      number to be added; stored as a double
1555
 * \return  0 if OK, 1 on error
1556
 *
1557
 * <pre>
1558
 * Notes:
1559
 *      (1) Adds to an existing l_dna only.
1560
 * </pre>
1561
 */
1562
l_ok
1563
l_dnaaAddNumber(L_DNAA    *daa,
1564
                l_int32    index,
1565
                l_float64  val)
1566
0
{
1567
0
l_int32  n;
1568
0
L_DNA   *da;
1569
1570
0
    if (!daa)
1571
0
        return ERROR_INT("daa not defined", __func__, 1);
1572
0
    n = l_dnaaGetCount(daa);
1573
0
    if (index < 0 || index >= n)
1574
0
        return ERROR_INT("invalid index in daa", __func__, 1);
1575
1576
0
    da = l_dnaaGetDna(daa, index, L_CLONE);
1577
0
    l_dnaAddNumber(da, val);
1578
0
    l_dnaDestroy(&da);
1579
0
    return 0;
1580
0
}
1581
1582
1583
/*----------------------------------------------------------------------*
1584
 *                        Serialize Dna for I/O                         *
1585
 *----------------------------------------------------------------------*/
1586
/*!
1587
 * \brief   l_dnaaRead()
1588
 *
1589
 * \param[in]    filename
1590
 * \return  daa, or NULL on error
1591
 */
1592
L_DNAA *
1593
l_dnaaRead(const char  *filename)
1594
0
{
1595
0
FILE    *fp;
1596
0
L_DNAA  *daa;
1597
1598
0
    if (!filename)
1599
0
        return (L_DNAA *)ERROR_PTR("filename not defined", __func__, NULL);
1600
1601
0
    if ((fp = fopenReadStream(filename)) == NULL)
1602
0
        return (L_DNAA *)ERROR_PTR_1("stream not opened",
1603
0
                                     filename, __func__, NULL);
1604
0
    daa = l_dnaaReadStream(fp);
1605
0
    fclose(fp);
1606
0
    if (!daa)
1607
0
        return (L_DNAA *)ERROR_PTR_1("daa not read",
1608
0
                                     filename, __func__, NULL);
1609
0
    return daa;
1610
0
}
1611
1612
1613
/*!
1614
 * \brief   l_dnaaReadStream()
1615
 *
1616
 * \param[in]    fp   file stream
1617
 * \return  daa, or NULL on error
1618
 *
1619
 * <pre>
1620
 * Notes:
1621
 *      (1) It is OK for the dnaa to be empty.
1622
 * </pre>
1623
 */
1624
L_DNAA *
1625
l_dnaaReadStream(FILE  *fp)
1626
0
{
1627
0
l_int32    i, n, index, ret, version;
1628
0
L_DNA     *da;
1629
0
L_DNAA    *daa;
1630
1631
0
    if (!fp)
1632
0
        return (L_DNAA *)ERROR_PTR("stream not defined", __func__, NULL);
1633
1634
0
    ret = fscanf(fp, "\nL_Dnaa Version %d\n", &version);
1635
0
    if (ret != 1)
1636
0
        return (L_DNAA *)ERROR_PTR("not a l_dna file", __func__, NULL);
1637
0
    if (version != DNA_VERSION_NUMBER)
1638
0
        return (L_DNAA *)ERROR_PTR("invalid l_dnaa version", __func__, NULL);
1639
0
    if (fscanf(fp, "Number of L_Dna = %d\n\n", &n) != 1)
1640
0
        return (L_DNAA *)ERROR_PTR("invalid number of l_dna", __func__, NULL);
1641
0
    if (n < 0)
1642
0
        return (L_DNAA *)ERROR_PTR("num l_dna <= 0", __func__, NULL);
1643
0
    if (n > MaxPtrArraySize)
1644
0
        return (L_DNAA *)ERROR_PTR("too many l_dna", __func__, NULL);
1645
0
    if (n == 0) L_INFO("the dnaa is empty\n", __func__);
1646
1647
0
    if ((daa = l_dnaaCreate(n)) == NULL)
1648
0
        return (L_DNAA *)ERROR_PTR("daa not made", __func__, NULL);
1649
0
    for (i = 0; i < n; i++) {
1650
0
        if (fscanf(fp, "L_Dna[%d]:", &index) != 1) {
1651
0
            l_dnaaDestroy(&daa);
1652
0
            return (L_DNAA *)ERROR_PTR("invalid l_dna header", __func__, NULL);
1653
0
        }
1654
0
        if ((da = l_dnaReadStream(fp)) == NULL) {
1655
0
            l_dnaaDestroy(&daa);
1656
0
            return (L_DNAA *)ERROR_PTR("da not made", __func__, NULL);
1657
0
        }
1658
0
        l_dnaaAddDna(daa, da, L_INSERT);
1659
0
    }
1660
1661
0
    return daa;
1662
0
}
1663
1664
1665
/*!
1666
 * \brief   l_dnaaReadMem()
1667
 *
1668
 * \param[in]    data     dnaa serialization; in ascii
1669
 * \param[in]    size     of data; can use strlen to get it
1670
 * \return  daa, or NULL on error
1671
 */
1672
L_DNAA *
1673
l_dnaaReadMem(const l_uint8  *data,
1674
              size_t          size)
1675
0
{
1676
0
FILE    *fp;
1677
0
L_DNAA  *daa;
1678
1679
0
    if (!data)
1680
0
        return (L_DNAA *)ERROR_PTR("data not defined", __func__, NULL);
1681
0
    if ((fp = fopenReadFromMemory(data, size)) == NULL)
1682
0
        return (L_DNAA *)ERROR_PTR("stream not opened", __func__, NULL);
1683
1684
0
    daa = l_dnaaReadStream(fp);
1685
0
    fclose(fp);
1686
0
    if (!daa) L_ERROR("daa not read\n", __func__);
1687
0
    return daa;
1688
0
}
1689
1690
1691
/*!
1692
 * \brief   l_dnaaWrite()
1693
 *
1694
 * \param[in]    filename
1695
 * \param[in]    daa
1696
 * \return  0 if OK, 1 on error
1697
 */
1698
l_ok
1699
l_dnaaWrite(const char  *filename,
1700
            L_DNAA      *daa)
1701
0
{
1702
0
l_int32  ret;
1703
0
FILE    *fp;
1704
1705
0
    if (!filename)
1706
0
        return ERROR_INT("filename not defined", __func__, 1);
1707
0
    if (!daa)
1708
0
        return ERROR_INT("daa not defined", __func__, 1);
1709
1710
0
    if ((fp = fopenWriteStream(filename, "w")) == NULL)
1711
0
        return ERROR_INT_1("stream not opened", filename, __func__, 1);
1712
0
    ret = l_dnaaWriteStream(fp, daa);
1713
0
    fclose(fp);
1714
0
    if (ret)
1715
0
        return ERROR_INT_1("daa not written to stream", filename, __func__, 1);
1716
0
    return 0;
1717
0
}
1718
1719
1720
/*!
1721
 * \brief   l_dnaaWriteStream()
1722
 *
1723
 * \param[in]    fp     file stream
1724
 * \param[in]    daa
1725
 * \return  0 if OK, 1 on error
1726
 */
1727
l_ok
1728
l_dnaaWriteStream(FILE    *fp,
1729
                  L_DNAA  *daa)
1730
0
{
1731
0
l_int32  i, n;
1732
0
L_DNA   *da;
1733
1734
0
    if (!fp)
1735
0
        return ERROR_INT("stream not defined", __func__, 1);
1736
0
    if (!daa)
1737
0
        return ERROR_INT("daa not defined", __func__, 1);
1738
1739
0
    n = l_dnaaGetCount(daa);
1740
0
    fprintf(fp, "\nL_Dnaa Version %d\n", DNA_VERSION_NUMBER);
1741
0
    fprintf(fp, "Number of L_Dna = %d\n\n", n);
1742
0
    for (i = 0; i < n; i++) {
1743
0
        if ((da = l_dnaaGetDna(daa, i, L_CLONE)) == NULL)
1744
0
            return ERROR_INT("da not found", __func__, 1);
1745
0
        fprintf(fp, "L_Dna[%d]:", i);
1746
0
        l_dnaWriteStream(fp, da);
1747
0
        l_dnaDestroy(&da);
1748
0
    }
1749
1750
0
    return 0;
1751
0
}
1752
1753
1754
/*!
1755
 * \brief   l_dnaaWriteMem()
1756
 *
1757
 * \param[out]   pdata    data of serialized dnaa; ascii
1758
 * \param[out]   psize    size of returned data
1759
 * \param[in]    daa
1760
 * \return  0 if OK, 1 on error
1761
 *
1762
 * <pre>
1763
 * Notes:
1764
 *      (1) Serializes a dnaa in memory and puts the result in a buffer.
1765
 * </pre>
1766
 */
1767
l_ok
1768
l_dnaaWriteMem(l_uint8  **pdata,
1769
               size_t    *psize,
1770
               L_DNAA    *daa)
1771
0
{
1772
0
l_int32  ret;
1773
0
FILE    *fp;
1774
1775
0
    if (pdata) *pdata = NULL;
1776
0
    if (psize) *psize = 0;
1777
0
    if (!pdata)
1778
0
        return ERROR_INT("&data not defined", __func__, 1);
1779
0
    if (!psize)
1780
0
        return ERROR_INT("&size not defined", __func__, 1);
1781
0
    if (!daa)
1782
0
        return ERROR_INT("daa not defined", __func__, 1);
1783
1784
0
#if HAVE_FMEMOPEN
1785
0
    if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1786
0
        return ERROR_INT("stream not opened", __func__, 1);
1787
0
    ret = l_dnaaWriteStream(fp, daa);
1788
0
    fputc('\0', fp);
1789
0
    fclose(fp);
1790
0
    if (*psize > 0) *psize = *psize - 1;
1791
#else
1792
    L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
1793
  #ifdef _WIN32
1794
    if ((fp = fopenWriteWinTempfile()) == NULL)
1795
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
1796
  #else
1797
    if ((fp = tmpfile()) == NULL)
1798
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
1799
  #endif  /* _WIN32 */
1800
    ret = l_dnaaWriteStream(fp, daa);
1801
    rewind(fp);
1802
    *pdata = l_binaryReadStream(fp, psize);
1803
    fclose(fp);
1804
#endif  /* HAVE_FMEMOPEN */
1805
0
    return ret;
1806
0
}
1807