Leptonica 1.83.1
Image processing and image analysis suite
Loading...
Searching...
No Matches
utils2.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
180
181#ifdef HAVE_CONFIG_H
182#include <config_auto.h>
183#endif /* HAVE_CONFIG_H */
184
185#ifdef _MSC_VER
186#include <process.h>
187#include <direct.h>
188#define getcwd _getcwd /* fix MSVC warning */
189#else
190#include <unistd.h>
191#endif /* _MSC_VER */
192
193#ifdef _WIN32
194#include <windows.h>
195#include <fcntl.h> /* _O_CREAT, ... */
196#include <io.h> /* _open */
197#include <sys/stat.h> /* _S_IREAD, _S_IWRITE */
198#else
199#include <sys/stat.h> /* for stat, mkdir(2) */
200#include <sys/types.h>
201#endif
202
203#ifdef __APPLE__
204#include <unistd.h>
205#include <errno.h>
206#endif
207
208#include <string.h>
209#include <stddef.h>
210#include "allheaders.h"
211
212
213/*--------------------------------------------------------------------*
214 * Safe string operations *
215 *--------------------------------------------------------------------*/
222char *
223stringNew(const char *src)
224{
225l_int32 len;
226char *dest;
227
228 if (!src) {
229 L_WARNING("src not defined\n", __func__);
230 return NULL;
231 }
232
233 len = strlen(src);
234 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
235 return (char *)ERROR_PTR("dest not made", __func__, NULL);
236
237 stringCopy(dest, src, len);
238 return dest;
239}
240
241
260l_ok
261stringCopy(char *dest,
262 const char *src,
263 l_int32 n)
264{
265l_int32 i;
266
267 if (!dest)
268 return ERROR_INT("dest not defined", __func__, 1);
269 if (!src || n < 1)
270 return 0;
271
272 /* Implementation of strncpy that valgrind doesn't complain about */
273 for (i = 0; i < n && src[i] != '\0'; i++)
274 dest[i] = src[i];
275 for (; i < n; i++)
276 dest[i] = '\0';
277 return 0;
278}
279
280
300char *
301stringCopySegment(const char *src,
302 l_int32 start,
303 l_int32 nbytes)
304{
305char *dest;
306l_int32 len;
307
308 if (!src)
309 return (char *)ERROR_PTR("src not defined", __func__, NULL);
310 len = strlen(src);
311 if (start < 0 || start > len - 1)
312 return (char *)ERROR_PTR("invalid start", __func__, NULL);
313 if (nbytes <= 0) /* copy to the end */
314 nbytes = len - start;
315 if (start + nbytes > len) /* truncate to the end */
316 nbytes = len - start;
317 if ((dest = (char *)LEPT_CALLOC(nbytes + 1, sizeof(char))) == NULL)
318 return (char *)ERROR_PTR("dest not made", __func__, NULL);
319 stringCopy(dest, src + start, nbytes);
320 return dest;
321}
322
323
338l_ok
339stringReplace(char **pdest,
340 const char *src)
341{
342 if (!pdest)
343 return ERROR_INT("pdest not defined", __func__, 1);
344
345 if (*pdest)
346 LEPT_FREE(*pdest);
347
348 if (src)
349 *pdest = stringNew(src);
350 else
351 *pdest = NULL;
352 return 0;
353}
354
355
372l_int32
373stringLength(const char *src,
374 size_t size)
375{
376l_int32 i;
377
378 if (!src)
379 return ERROR_INT("src not defined", __func__, 0);
380 if (size < 1)
381 return 0;
382
383 for (i = 0; i < size; i++) {
384 if (src[i] == '\0')
385 return i;
386 }
387 return size; /* didn't find a NUL byte */
388}
389
390
412l_int32
413stringCat(char *dest,
414 size_t size,
415 const char *src)
416{
417l_int32 i, n;
418l_int32 lendest, lensrc;
419
420 if (!dest)
421 return ERROR_INT("dest not defined", __func__, -1);
422 if (size < 1)
423 return ERROR_INT("size < 1; too small", __func__, -1);
424 if (!src)
425 return 0;
426
427 lendest = stringLength(dest, size);
428 if (lendest == size)
429 return ERROR_INT("no terminating nul byte", __func__, -1);
430 lensrc = stringLength(src, size);
431 if (lensrc == 0)
432 return 0;
433 n = (lendest + lensrc > size - 1 ? 0 : lensrc);
434 if (n < 1)
435 return ERROR_INT("dest too small for append", __func__, -1);
436
437 for (i = 0; i < n; i++)
438 dest[lendest + i] = src[i];
439 dest[lendest + n] = '\0';
440 return n;
441}
442
443
458char *
459stringConcatNew(const char *first, ...)
460{
461size_t len;
462char *result, *ptr;
463const char *arg;
464va_list args;
465
466 if (!first) return NULL;
467
468 /* Find the length of the output string */
469 va_start(args, first);
470 len = strlen(first);
471 while ((arg = va_arg(args, const char *)) != NULL)
472 len += strlen(arg);
473 va_end(args);
474 result = (char *)LEPT_CALLOC(len + 1, sizeof(char));
475
476 /* Concatenate the args */
477 va_start(args, first);
478 ptr = result;
479 arg = first;
480 while (*arg)
481 *ptr++ = *arg++;
482 while ((arg = va_arg(args, const char *)) != NULL) {
483 while (*arg)
484 *ptr++ = *arg++;
485 }
486 va_end(args);
487 return result;
488}
489
490
505char *
506stringJoin(const char *src1,
507 const char *src2)
508{
509char *dest;
510l_int32 srclen1, srclen2, destlen;
511
512 srclen1 = (src1) ? strlen(src1) : 0;
513 srclen2 = (src2) ? strlen(src2) : 0;
514 destlen = srclen1 + srclen2 + 3;
515
516 if ((dest = (char *)LEPT_CALLOC(destlen, sizeof(char))) == NULL)
517 return (char *)ERROR_PTR("calloc fail for dest", __func__, NULL);
518
519 if (src1)
520 stringCat(dest, destlen, src1);
521 if (src2)
522 stringCat(dest, destlen, src2);
523 return dest;
524}
525
526
558l_ok
559stringJoinIP(char **psrc1,
560 const char *src2)
561{
562char *tmpstr;
563
564 if (!psrc1)
565 return ERROR_INT("&src1 not defined", __func__, 1);
566
567 tmpstr = stringJoin(*psrc1, src2);
568 LEPT_FREE(*psrc1);
569 *psrc1 = tmpstr;
570 return 0;
571}
572
573
580char *
581stringReverse(const char *src)
582{
583char *dest;
584l_int32 i, len;
585
586 if (!src)
587 return (char *)ERROR_PTR("src not defined", __func__, NULL);
588 len = strlen(src);
589 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
590 return (char *)ERROR_PTR("calloc fail for dest", __func__, NULL);
591 for (i = 0; i < len; i++)
592 dest[i] = src[len - 1 - i];
593
594 return dest;
595}
596
597
630char *
631strtokSafe(char *cstr,
632 const char *seps,
633 char **psaveptr)
634{
635char nextc;
636char *start, *substr;
637l_int32 istart, i, j, nchars;
638
639 if (!seps)
640 return (char *)ERROR_PTR("seps not defined", __func__, NULL);
641 if (!psaveptr)
642 return (char *)ERROR_PTR("&saveptr not defined", __func__, NULL);
643
644 if (!cstr) {
645 start = *psaveptr;
646 } else {
647 start = cstr;
648 *psaveptr = NULL;
649 }
650 if (!start) /* nothing to do */
651 return NULL;
652
653 /* First time, scan for the first non-sep character */
654 istart = 0;
655 if (cstr) {
656 for (istart = 0;; istart++) {
657 if ((nextc = start[istart]) == '\0') {
658 *psaveptr = NULL; /* in case caller doesn't check ret value */
659 return NULL;
660 }
661 if (!strchr(seps, nextc))
662 break;
663 }
664 }
665
666 /* Scan through, looking for a sep character; if none is
667 * found, 'i' will be at the end of the string. */
668 for (i = istart;; i++) {
669 if ((nextc = start[i]) == '\0')
670 break;
671 if (strchr(seps, nextc))
672 break;
673 }
674
675 /* Save the substring */
676 nchars = i - istart;
677 substr = (char *)LEPT_CALLOC(nchars + 1, sizeof(char));
678 stringCopy(substr, start + istart, nchars);
679
680 /* Look for the next non-sep character.
681 * If this is the last substring, return a null saveptr. */
682 for (j = i;; j++) {
683 if ((nextc = start[j]) == '\0') {
684 *psaveptr = NULL; /* no more non-sep characters */
685 break;
686 }
687 if (!strchr(seps, nextc)) {
688 *psaveptr = start + j; /* start here on next call */
689 break;
690 }
691 }
692
693 return substr;
694}
695
696
722l_ok
724 const char *seps,
725 char **phead,
726 char **ptail)
727{
728char *saveptr;
729
730 if (!phead)
731 return ERROR_INT("&head not defined", __func__, 1);
732 if (!ptail)
733 return ERROR_INT("&tail not defined", __func__, 1);
734 *phead = *ptail = NULL;
735 if (!cstr)
736 return ERROR_INT("cstr not defined", __func__, 1);
737 if (!seps)
738 return ERROR_INT("seps not defined", __func__, 1);
739
740 *phead = strtokSafe(cstr, seps, &saveptr);
741 if (saveptr)
742 *ptail = stringNew(saveptr);
743 return 0;
744}
745
746
747/*--------------------------------------------------------------------*
748 * Find and replace procs *
749 *--------------------------------------------------------------------*/
764l_ok
765stringCheckForChars(const char *src,
766 const char *chars,
767 l_int32 *pfound)
768{
769char ch;
770l_int32 i, n;
771
772 if (!pfound)
773 return ERROR_INT("&found not defined", __func__, 1);
774 *pfound = FALSE;
775 if (!src || !chars)
776 return ERROR_INT("src and chars not both defined", __func__, 1);
777
778 n = strlen(src);
779 for (i = 0; i < n; i++) {
780 ch = src[i];
781 if (strchr(chars, ch)) {
782 *pfound = TRUE;
783 break;
784 }
785 }
786 return 0;
787}
788
789
797char *
798stringRemoveChars(const char *src,
799 const char *remchars)
800{
801char ch;
802char *dest;
803l_int32 nsrc, i, k;
804
805 if (!src)
806 return (char *)ERROR_PTR("src not defined", __func__, NULL);
807 if (!remchars)
808 return stringNew(src);
809
810 if ((dest = (char *)LEPT_CALLOC(strlen(src) + 1, sizeof(char))) == NULL)
811 return (char *)ERROR_PTR("dest not made", __func__, NULL);
812 nsrc = strlen(src);
813 for (i = 0, k = 0; i < nsrc; i++) {
814 ch = src[i];
815 if (!strchr(remchars, ch))
816 dest[k++] = ch;
817 }
818
819 return dest;
820}
821
822
851char *
853 const char *sub1,
854 const char *sub2,
855 l_int32 *pcount)
856{
857size_t datalen;
858
859 if (pcount) *pcount = 0;
860 if (!src || !sub1 || !sub2)
861 return (char *)ERROR_PTR("src, sub1, sub2 not all defined",
862 __func__, NULL);
863
864 if (strlen(sub2) > 0) {
865 return (char *)arrayReplaceEachSequence(
866 (const l_uint8 *)src, strlen(src),
867 (const l_uint8 *)sub1, strlen(sub1),
868 (const l_uint8 *)sub2, strlen(sub2),
869 &datalen, pcount);
870 } else { /* empty replacement string; removal only */
871 return (char *)arrayReplaceEachSequence(
872 (const l_uint8 *)src, strlen(src),
873 (const l_uint8 *)sub1, strlen(sub1),
874 NULL, 0, &datalen, pcount);
875 }
876}
877
878
906char *
907stringReplaceSubstr(const char *src,
908 const char *sub1,
909 const char *sub2,
910 l_int32 *ploc,
911 l_int32 *pfound)
912{
913const char *ptr;
914char *dest;
915l_int32 nsrc, nsub1, nsub2, len, npre, loc;
916
917 if (pfound) *pfound = 0;
918 if (!src || !sub1 || !sub2)
919 return (char *)ERROR_PTR("src, sub1, sub2 not all defined",
920 __func__, NULL);
921
922 if (ploc)
923 loc = *ploc;
924 else
925 loc = 0;
926 if (!strcmp(sub1, sub2))
927 return stringNew(src);
928 if ((ptr = strstr(src + loc, sub1)) == NULL)
929 return stringNew(src);
930 if (pfound) *pfound = 1;
931
932 nsrc = strlen(src);
933 nsub1 = strlen(sub1);
934 nsub2 = strlen(sub2);
935 len = nsrc + nsub2 - nsub1;
936 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
937 return (char *)ERROR_PTR("dest not made", __func__, NULL);
938 npre = ptr - src;
939 memcpy(dest, src, npre);
940 strcpy(dest + npre, sub2);
941 strcpy(dest + npre + nsub2, ptr + nsub1);
942 if (ploc) *ploc = npre + nsub2;
943 return dest;
944}
945
946
965L_DNA *
966stringFindEachSubstr(const char *src,
967 const char *sub)
968{
969 if (!src || !sub)
970 return (L_DNA *)ERROR_PTR("src, sub not both defined", __func__, NULL);
971
972 return arrayFindEachSequence((const l_uint8 *)src, strlen(src),
973 (const l_uint8 *)sub, strlen(sub));
974}
975
976
994l_int32
995stringFindSubstr(const char *src,
996 const char *sub,
997 l_int32 *ploc)
998{
999const char *ptr;
1000
1001 if (ploc) *ploc = -1;
1002 if (!src || !sub)
1003 return ERROR_INT("src and sub not both defined", __func__, 0);
1004 if (strlen(sub) == 0)
1005 return ERROR_INT("substring length 0", __func__, 0);
1006 if (strlen(src) == 0)
1007 return 0;
1008
1009 if ((ptr = strstr(src, sub)) == NULL) /* not found */
1010 return 0;
1011
1012 if (ploc)
1013 *ploc = ptr - src;
1014 return 1;
1015}
1016
1017
1047l_uint8 *
1048arrayReplaceEachSequence(const l_uint8 *datas,
1049 size_t dataslen,
1050 const l_uint8 *seq,
1051 size_t seqlen,
1052 const l_uint8 *newseq,
1053 size_t newseqlen,
1054 size_t *pdatadlen,
1055 l_int32 *pcount)
1056{
1057l_uint8 *datad;
1058size_t newsize;
1059l_int32 n, i, j, di, si, index, incr;
1060L_DNA *da;
1061
1062 if (pcount) *pcount = 0;
1063 if (!datas || !seq)
1064 return (l_uint8 *)ERROR_PTR("datas & seq not both defined",
1065 __func__, NULL);
1066 if (!pdatadlen)
1067 return (l_uint8 *)ERROR_PTR("&datadlen not defined", __func__, NULL);
1068 *pdatadlen = 0;
1069
1070 /* Identify the locations of the sequence. If there are none,
1071 * return a copy of %datas. */
1072 if ((da = arrayFindEachSequence(datas, dataslen, seq, seqlen)) == NULL) {
1073 *pdatadlen = dataslen;
1074 return l_binaryCopy(datas, dataslen);
1075 }
1076
1077 /* Allocate the output data; insure null termination */
1078 n = l_dnaGetCount(da);
1079 if (pcount) *pcount = n;
1080 if (!newseq) newseqlen = 0;
1081 newsize = dataslen + n * (newseqlen - seqlen) + 4;
1082 if ((datad = (l_uint8 *)LEPT_CALLOC(newsize, sizeof(l_uint8))) == NULL) {
1083 l_dnaDestroy(&da);
1084 return (l_uint8 *)ERROR_PTR("datad not made", __func__, NULL);
1085 }
1086
1087 /* Replace each sequence instance with a new sequence */
1088 l_dnaGetIValue(da, 0, &si);
1089 for (i = 0, di = 0, index = 0; i < dataslen; i++) {
1090 if (i == si) {
1091 index++;
1092 if (index < n) {
1093 l_dnaGetIValue(da, index, &si);
1094 incr = L_MIN(seqlen, si - i); /* amount to remove from datas */
1095 } else {
1096 incr = seqlen;
1097 }
1098 i += incr - 1; /* jump over the matched sequence in datas */
1099 if (newseq) { /* add new sequence to datad */
1100 for (j = 0; j < newseqlen; j++)
1101 datad[di++] = newseq[j];
1102 }
1103 } else {
1104 datad[di++] = datas[i];
1105 }
1106 }
1107
1108 *pdatadlen = di;
1109 l_dnaDestroy(&da);
1110 return datad;
1111}
1112
1113
1136L_DNA *
1137arrayFindEachSequence(const l_uint8 *data,
1138 size_t datalen,
1139 const l_uint8 *sequence,
1140 size_t seqlen)
1141{
1142l_int32 start, offset, realoffset, found;
1143L_DNA *da;
1144
1145 if (!data || !sequence)
1146 return (L_DNA *)ERROR_PTR("data & sequence not both defined",
1147 __func__, NULL);
1148
1149 da = l_dnaCreate(0);
1150 start = 0;
1151 while (1) {
1152 arrayFindSequence(data + start, datalen - start, sequence, seqlen,
1153 &offset, &found);
1154 if (found == FALSE)
1155 break;
1156
1157 realoffset = start + offset;
1158 l_dnaAddNumber(da, realoffset);
1159 start = realoffset + seqlen;
1160 if (start >= datalen)
1161 break;
1162 }
1163
1164 if (l_dnaGetCount(da) == 0)
1165 l_dnaDestroy(&da);
1166 return da;
1167}
1168
1169
1194l_ok
1195arrayFindSequence(const l_uint8 *data,
1196 size_t datalen,
1197 const l_uint8 *sequence,
1198 size_t seqlen,
1199 l_int32 *poffset,
1200 l_int32 *pfound)
1201{
1202l_int32 i, j, found, lastpos;
1203
1204 if (poffset) *poffset = 0;
1205 if (pfound) *pfound = FALSE;
1206 if (!data || !sequence)
1207 return ERROR_INT("data & sequence not both defined", __func__, 1);
1208 if (!poffset || !pfound)
1209 return ERROR_INT("&offset and &found not defined", __func__, 1);
1210
1211 lastpos = datalen - seqlen + 1;
1212 found = FALSE;
1213 for (i = 0; i < lastpos; i++) {
1214 for (j = 0; j < seqlen; j++) {
1215 if (data[i + j] != sequence[j])
1216 break;
1217 if (j == seqlen - 1)
1218 found = TRUE;
1219 }
1220 if (found == TRUE)
1221 break;
1222 }
1223
1224 if (found == TRUE) {
1225 *poffset = i;
1226 *pfound = TRUE;
1227 }
1228 return 0;
1229}
1230
1231
1232/*--------------------------------------------------------------------*
1233 * Safe realloc *
1234 *--------------------------------------------------------------------*/
1261void *
1262reallocNew(void **pindata,
1263 size_t oldsize,
1264 size_t newsize)
1265{
1266size_t minsize;
1267void *indata;
1268void *newdata;
1269
1270 if (!pindata)
1271 return ERROR_PTR("input data not defined", __func__, NULL);
1272 indata = *pindata;
1273
1274 if (newsize == 0) { /* nonstandard usage */
1275 if (indata) {
1276 LEPT_FREE(indata);
1277 *pindata = NULL;
1278 }
1279 return NULL;
1280 }
1281
1282 if (!indata) { /* nonstandard usage */
1283 if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1284 return ERROR_PTR("newdata not made", __func__, NULL);
1285 return newdata;
1286 }
1287
1288 /* Standard usage */
1289 if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1290 return ERROR_PTR("newdata not made", __func__, NULL);
1291 minsize = L_MIN(oldsize, newsize);
1292 memcpy(newdata, indata, minsize);
1293 LEPT_FREE(indata);
1294 *pindata = NULL;
1295 return newdata;
1296}
1297
1298
1299/*--------------------------------------------------------------------*
1300 * Read and write between file and memory *
1301 *--------------------------------------------------------------------*/
1309l_uint8 *
1310l_binaryRead(const char *filename,
1311 size_t *pnbytes)
1312{
1313l_uint8 *data;
1314FILE *fp;
1315
1316 if (!pnbytes)
1317 return (l_uint8 *)ERROR_PTR("pnbytes not defined", __func__, NULL);
1318 *pnbytes = 0;
1319 if (!filename)
1320 return (l_uint8 *)ERROR_PTR("filename not defined", __func__, NULL);
1321
1322 if ((fp = fopenReadStream(filename)) == NULL)
1323 return (l_uint8 *)ERROR_PTR("file stream not opened", __func__, NULL);
1324 data = l_binaryReadStream(fp, pnbytes);
1325 fclose(fp);
1326 return data;
1327}
1328
1329
1357l_uint8 *
1359 size_t *pnbytes)
1360{
1361l_uint8 *data;
1362l_int32 seekable, navail, nadd, nread;
1363L_BBUFFER *bb;
1364
1365 if (!pnbytes)
1366 return (l_uint8 *)ERROR_PTR("&nbytes not defined", __func__, NULL);
1367 *pnbytes = 0;
1368 if (!fp)
1369 return (l_uint8 *)ERROR_PTR("fp not defined", __func__, NULL);
1370
1371 /* Test if the stream is seekable, by attempting to seek to
1372 * the start of data. This is a no-op. If it is seekable, use
1373 * l_binaryReadSelectStream() to determine the size of the
1374 * data to be read in advance. */
1375 seekable = (ftell(fp) == 0) ? 1 : 0;
1376 if (seekable)
1377 return l_binaryReadSelectStream(fp, 0, 0, pnbytes);
1378
1379 /* If it is not seekable, use the bbuffer to realloc memory
1380 * as needed during reading. */
1381 bb = bbufferCreate(NULL, 4096);
1382 while (1) {
1383 navail = bb->nalloc - bb->n;
1384 if (navail < 4096) {
1385 nadd = L_MAX(bb->nalloc, 4096);
1386 bbufferExtendArray(bb, nadd);
1387 }
1388 nread = fread((void *)(bb->array + bb->n), 1, 4096, fp);
1389 bb->n += nread;
1390 if (nread != 4096) break;
1391 }
1392
1393 /* Copy the data to a new array sized for the data, because
1394 * the bbuffer array can be nearly twice the size we need. */
1395 if ((data = (l_uint8 *)LEPT_CALLOC(bb->n + 1, sizeof(l_uint8))) != NULL) {
1396 memcpy(data, bb->array, bb->n);
1397 *pnbytes = bb->n;
1398 } else {
1399 L_ERROR("calloc fail for data\n", __func__);
1400 }
1401
1402 bbufferDestroy(&bb);
1403 return data;
1404}
1405
1406
1422l_uint8 *
1423l_binaryReadSelect(const char *filename,
1424 size_t start,
1425 size_t nbytes,
1426 size_t *pnread)
1427{
1428l_uint8 *data;
1429FILE *fp;
1430
1431 if (!pnread)
1432 return (l_uint8 *)ERROR_PTR("pnread not defined", __func__, NULL);
1433 *pnread = 0;
1434 if (!filename)
1435 return (l_uint8 *)ERROR_PTR("filename not defined", __func__, NULL);
1436
1437 if ((fp = fopenReadStream(filename)) == NULL)
1438 return (l_uint8 *)ERROR_PTR("file stream not opened", __func__, NULL);
1439 data = l_binaryReadSelectStream(fp, start, nbytes, pnread);
1440 fclose(fp);
1441 return data;
1442}
1443
1444
1465l_uint8 *
1467 size_t start,
1468 size_t nbytes,
1469 size_t *pnread)
1470{
1471l_uint8 *data;
1472size_t bytesleft, bytestoread, nread, filebytes;
1473
1474 if (!pnread)
1475 return (l_uint8 *)ERROR_PTR("&nread not defined", __func__, NULL);
1476 *pnread = 0;
1477 if (!fp)
1478 return (l_uint8 *)ERROR_PTR("stream not defined", __func__, NULL);
1479
1480 /* Verify and adjust the parameters if necessary */
1481 fseek(fp, 0, SEEK_END); /* EOF */
1482 filebytes = ftell(fp);
1483 fseek(fp, 0, SEEK_SET);
1484 if (start > filebytes) {
1485 L_ERROR("start = %zu but filebytes = %zu\n", __func__,
1486 start, filebytes);
1487 return NULL;
1488 }
1489 if (filebytes == 0) /* start == 0; nothing to read; return null byte */
1490 return (l_uint8 *)LEPT_CALLOC(1, 1);
1491 bytesleft = filebytes - start; /* greater than 0 */
1492 if (nbytes == 0) nbytes = bytesleft;
1493 bytestoread = (bytesleft >= nbytes) ? nbytes : bytesleft;
1494
1495 /* Read the data */
1496 if ((data = (l_uint8 *)LEPT_CALLOC(1, bytestoread + 1)) == NULL)
1497 return (l_uint8 *)ERROR_PTR("calloc fail for data", __func__, NULL);
1498 fseek(fp, start, SEEK_SET);
1499 nread = fread(data, 1, bytestoread, fp);
1500 if (nbytes != nread)
1501 L_INFO("%zu bytes requested; %zu bytes read\n", __func__,
1502 nbytes, nread);
1503 *pnread = nread;
1504 fseek(fp, 0, SEEK_SET);
1505 return data;
1506}
1507
1508
1518l_ok
1519l_binaryWrite(const char *filename,
1520 const char *operation,
1521 const void *data,
1522 size_t nbytes)
1523{
1524char actualOperation[20];
1525FILE *fp;
1526
1527 if (!filename)
1528 return ERROR_INT("filename not defined", __func__, 1);
1529 if (!operation)
1530 return ERROR_INT("operation not defined", __func__, 1);
1531 if (!data)
1532 return ERROR_INT("data not defined", __func__, 1);
1533 if (nbytes <= 0)
1534 return ERROR_INT("nbytes must be > 0", __func__, 1);
1535
1536 if (strcmp(operation, "w") && strcmp(operation, "a"))
1537 return ERROR_INT("operation not one of {'w','a'}", __func__, 1);
1538
1539 /* The 'b' flag to fopen() is ignored for all POSIX
1540 * conforming systems. However, Windows needs the 'b' flag. */
1541 stringCopy(actualOperation, operation, 2);
1542 stringCat(actualOperation, 20, "b");
1543
1544 if ((fp = fopenWriteStream(filename, actualOperation)) == NULL)
1545 return ERROR_INT("stream not opened", __func__, 1);
1546 fwrite(data, 1, nbytes, fp);
1547 fclose(fp);
1548 return 0;
1549}
1550
1551
1558size_t
1559nbytesInFile(const char *filename)
1560{
1561size_t nbytes;
1562FILE *fp;
1563
1564 if (!filename)
1565 return ERROR_INT("filename not defined", __func__, 0);
1566 if ((fp = fopenReadStream(filename)) == NULL)
1567 return ERROR_INT("stream not opened", __func__, 0);
1568 nbytes = fnbytesInFile(fp);
1569 fclose(fp);
1570 return nbytes;
1571}
1572
1573
1580size_t
1582{
1583l_int64 pos, nbytes;
1584
1585 if (!fp)
1586 return ERROR_INT("stream not open", __func__, 0);
1587
1588 pos = ftell(fp); /* initial position */
1589 if (pos < 0)
1590 return ERROR_INT("seek position must be > 0", __func__, 0);
1591 fseek(fp, 0, SEEK_END); /* EOF */
1592 nbytes = ftell(fp);
1593 if (nbytes < 0)
1594 return ERROR_INT("nbytes is < 0", __func__, 0);
1595 fseek(fp, pos, SEEK_SET); /* back to initial position */
1596 return nbytes;
1597}
1598
1599
1600/*--------------------------------------------------------------------*
1601 * Copy and compare in memory *
1602 *--------------------------------------------------------------------*/
1618l_uint8 *
1619l_binaryCopy(const l_uint8 *datas,
1620 size_t size)
1621{
1622l_uint8 *datad;
1623
1624 if (!datas)
1625 return (l_uint8 *)ERROR_PTR("datas not defined", __func__, NULL);
1626
1627 if ((datad = (l_uint8 *)LEPT_CALLOC(size + 4, sizeof(l_uint8))) == NULL)
1628 return (l_uint8 *)ERROR_PTR("datad not made", __func__, NULL);
1629 memcpy(datad, datas, size);
1630 return datad;
1631}
1632
1633
1652l_ok
1653l_binaryCompare(const l_uint8 *data1,
1654 size_t size1,
1655 const l_uint8 *data2,
1656 size_t size2,
1657 l_int32 *psame)
1658{
1659l_int32 i;
1660
1661 if (!psame)
1662 return ERROR_INT("&same not defined", __func__, 1);
1663 *psame = FALSE;
1664 if (!data1 || !data2)
1665 return ERROR_INT("data1 and data2 not both defined", __func__, 1);
1666 if (size1 != size2) return 0;
1667 for (i = 0; i < size1; i++) {
1668 if (data1[i] != data2[i])
1669 return 0;
1670 }
1671 *psame = TRUE;
1672 return 0;
1673}
1674
1675
1676/*--------------------------------------------------------------------*
1677 * File copy operations *
1678 *--------------------------------------------------------------------*/
1686l_ok
1687fileCopy(const char *srcfile,
1688 const char *newfile)
1689{
1690l_int32 ret;
1691size_t nbytes;
1692l_uint8 *data;
1693
1694 if (!srcfile)
1695 return ERROR_INT("srcfile not defined", __func__, 1);
1696 if (!newfile)
1697 return ERROR_INT("newfile not defined", __func__, 1);
1698
1699 if ((data = l_binaryRead(srcfile, &nbytes)) == NULL)
1700 return ERROR_INT("data not returned", __func__, 1);
1701 ret = l_binaryWrite(newfile, "w", data, nbytes);
1702 LEPT_FREE(data);
1703 return ret;
1704}
1705
1706
1714l_ok
1715fileConcatenate(const char *srcfile,
1716 const char *destfile)
1717{
1718size_t nbytes;
1719l_uint8 *data;
1720
1721 if (!srcfile)
1722 return ERROR_INT("srcfile not defined", __func__, 1);
1723 if (!destfile)
1724 return ERROR_INT("destfile not defined", __func__, 1);
1725
1726 data = l_binaryRead(srcfile, &nbytes);
1727 l_binaryWrite(destfile, "a", data, nbytes);
1728 LEPT_FREE(data);
1729 return 0;
1730}
1731
1732
1740l_ok
1741fileAppendString(const char *filename,
1742 const char *str)
1743{
1744FILE *fp;
1745
1746 if (!filename)
1747 return ERROR_INT("filename not defined", __func__, 1);
1748 if (!str)
1749 return ERROR_INT("str not defined", __func__, 1);
1750
1751 if ((fp = fopenWriteStream(filename, "a")) == NULL)
1752 return ERROR_INT("stream not opened", __func__, 1);
1753 fprintf(fp, "%s", str);
1754 fclose(fp);
1755 return 0;
1756}
1757
1758
1759/*--------------------------------------------------------------------*
1760 * File split operations *
1761 *--------------------------------------------------------------------*/
1788l_ok
1789fileSplitLinesUniform(const char *filename,
1790 l_int32 n,
1791 l_int32 save_empty,
1792 const char *rootpath,
1793 const char *ext)
1794{
1795l_int32 i, totlines, nlines, index;
1796size_t nbytes;
1797l_uint8 *data;
1798char *str;
1799char outname[512];
1800NUMA *na;
1801SARRAY *sa;
1802
1803 if (!filename)
1804 return ERROR_INT("filename not defined", __func__, 1);
1805 if (!rootpath)
1806 return ERROR_INT("rootpath not defined", __func__, 1);
1807 if (n <= 0)
1808 return ERROR_INT("n must be > 0", __func__, 1);
1809 if (save_empty != 0 && save_empty != 1)
1810 return ERROR_INT("save_empty not 0 or 1", __func__, 1);
1811
1812 /* Make sarray of lines; the newlines are stripped off */
1813 if ((data = l_binaryRead(filename, &nbytes)) == NULL)
1814 return ERROR_INT("data not read", __func__, 1);
1815 sa = sarrayCreateLinesFromString((const char *)data, save_empty);
1816 LEPT_FREE(data);
1817 if (!sa)
1818 return ERROR_INT("sa not made", __func__, 1);
1819 totlines = sarrayGetCount(sa);
1820 if (n > totlines) {
1821 sarrayDestroy(&sa);
1822 L_ERROR("num files = %d > num lines = %d\n", __func__, n, totlines);
1823 return 1;
1824 }
1825
1826 /* Write n sets of lines to n files, adding the newlines back */
1827 na = numaGetUniformBinSizes(totlines, n);
1828 index = 0;
1829 for (i = 0; i < n; i++) {
1830 if (ext == NULL)
1831 snprintf(outname, sizeof(outname), "%s_%d", rootpath, i);
1832 else
1833 snprintf(outname, sizeof(outname), "%s_%d%s", rootpath, i, ext);
1834 numaGetIValue(na, i, &nlines);
1835 str = sarrayToStringRange(sa, index, nlines, 1); /* add newlines */
1836 l_binaryWrite(outname, "w", str, strlen(str));
1837 LEPT_FREE(str);
1838 index += nlines;
1839 }
1840 numaDestroy(&na);
1841 sarrayDestroy(&sa);
1842 return 0;
1843}
1844
1845
1846/*--------------------------------------------------------------------*
1847 * Multi-platform functions for opening file streams *
1848 *--------------------------------------------------------------------*/
1863FILE *
1864fopenReadStream(const char *filename)
1865{
1866char *fname, *tail;
1867FILE *fp;
1868
1869 if (!filename)
1870 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
1871
1872 /* Try input filename */
1873 fname = genPathname(filename, NULL);
1874 fp = fopen(fname, "rb");
1875 LEPT_FREE(fname);
1876 if (fp) return fp;
1877
1878 /* Else, strip directory and try locally */
1879 splitPathAtDirectory(filename, NULL, &tail);
1880 fp = fopen(tail, "rb");
1881 LEPT_FREE(tail);
1882
1883 if (!fp)
1884 return (FILE *)ERROR_PTR("file not found", __func__, NULL);
1885 return fp;
1886}
1887
1888
1904FILE *
1905fopenWriteStream(const char *filename,
1906 const char *modestring)
1907{
1908char *fname;
1909FILE *fp;
1910
1911 if (!filename)
1912 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
1913
1914 fname = genPathname(filename, NULL);
1915 fp = fopen(fname, modestring);
1916 LEPT_FREE(fname);
1917 if (!fp)
1918 return (FILE *)ERROR_PTR("stream not opened", __func__, NULL);
1919 return fp;
1920}
1921
1922
1936FILE *
1937fopenReadFromMemory(const l_uint8 *data,
1938 size_t size)
1939{
1940FILE *fp;
1941
1942 if (!data)
1943 return (FILE *)ERROR_PTR("data not defined", __func__, NULL);
1944
1945#if HAVE_FMEMOPEN
1946 if ((fp = fmemopen((void *)data, size, "rb")) == NULL)
1947 return (FILE *)ERROR_PTR("stream not opened", __func__, NULL);
1948#else /* write to tmp file */
1949 L_INFO("work-around: writing to a temp file\n", __func__);
1950 #ifdef _WIN32
1951 if ((fp = fopenWriteWinTempfile()) == NULL)
1952 return (FILE *)ERROR_PTR("tmpfile stream not opened", __func__, NULL);
1953 #else
1954 if ((fp = tmpfile()) == NULL)
1955 return (FILE *)ERROR_PTR("tmpfile stream not opened", __func__, NULL);
1956 #endif /* _WIN32 */
1957 fwrite(data, 1, size, fp);
1958 rewind(fp);
1959#endif /* HAVE_FMEMOPEN */
1960
1961 return fp;
1962}
1963
1964
1965/*--------------------------------------------------------------------*
1966 * Opening a Windows tmpfile for writing *
1967 *--------------------------------------------------------------------*/
1980FILE *
1982{
1983#ifdef _WIN32
1984l_int32 handle;
1985FILE *fp;
1986char *filename;
1987
1988 if ((filename = l_makeTempFilename()) == NULL) {
1989 L_ERROR("l_makeTempFilename failed, %s\n", __func__, strerror(errno));
1990 return NULL;
1991 }
1992
1993 handle = _open(filename, _O_CREAT | _O_RDWR | _O_SHORT_LIVED |
1994 _O_TEMPORARY | _O_BINARY, _S_IREAD | _S_IWRITE);
1995 lept_free(filename);
1996 if (handle == -1) {
1997 L_ERROR("_open failed, %s\n", __func__, strerror(errno));
1998 return NULL;
1999 }
2000
2001 if ((fp = _fdopen(handle, "r+b")) == NULL) {
2002 L_ERROR("_fdopen failed, %s\n", __func__, strerror(errno));
2003 return NULL;
2004 }
2005
2006 return fp;
2007#else
2008 return NULL;
2009#endif /* _WIN32 */
2010}
2011
2012
2013/*--------------------------------------------------------------------*
2014 * Multi-platform functions that avoid C-runtime boundary *
2015 * crossing for applications with Windows DLLs *
2016 *--------------------------------------------------------------------*/
2017/*
2018 * Problems arise when pointers to streams and data are passed
2019 * between two Windows DLLs that have been generated with different
2020 * C runtimes. To avoid this, leptonica provides wrappers for
2021 * several C library calls.
2022 */
2036FILE *
2037lept_fopen(const char *filename,
2038 const char *mode)
2039{
2040 if (!filename)
2041 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
2042 if (!mode)
2043 return (FILE *)ERROR_PTR("mode not defined", __func__, NULL);
2044
2045 if (stringFindSubstr(mode, "r", NULL))
2046 return fopenReadStream(filename);
2047 else
2048 return fopenWriteStream(filename, mode);
2049}
2050
2051
2064l_ok
2066{
2067 if (!fp)
2068 return ERROR_INT("stream not defined", __func__, 1);
2069
2070 return fclose(fp);
2071}
2072
2073
2088void *
2089lept_calloc(size_t nmemb,
2090 size_t size)
2091{
2092 if (nmemb <= 0 || size <= 0)
2093 return NULL;
2094 return LEPT_CALLOC(nmemb, size);
2095}
2096
2097
2109void
2110lept_free(void *ptr)
2111{
2112 if (!ptr) return;
2113 LEPT_FREE(ptr);
2114}
2115
2116
2117/*--------------------------------------------------------------------*
2118 * Multi-platform file system operations *
2119 * [ These only write to /tmp or its subdirectories ] *
2120 *--------------------------------------------------------------------*/
2137l_int32
2138lept_mkdir(const char *subdir)
2139{
2140char *dir, *tmpdir;
2141l_int32 i, n;
2142l_int32 ret = 0;
2143SARRAY *sa;
2144#ifdef _WIN32
2145l_uint32 attributes;
2146#endif /* _WIN32 */
2147
2148 if (!LeptDebugOK) {
2149 L_INFO("making named temp subdirectory %s is disabled\n",
2150 __func__, subdir);
2151 return 0;
2152 }
2153
2154 if (!subdir)
2155 return ERROR_INT("subdir not defined", __func__, 1);
2156 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2157 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
2158
2159 sa = sarrayCreate(0);
2160 sarraySplitString(sa, subdir, "/");
2161 n = sarrayGetCount(sa);
2162 dir = genPathname("/tmp", NULL);
2163 /* Make sure the tmp directory exists */
2164#ifndef _WIN32
2165 ret = mkdir(dir, 0777);
2166#else
2167 attributes = GetFileAttributes(dir);
2168 if (attributes == INVALID_FILE_ATTRIBUTES)
2169 ret = (CreateDirectory(dir, NULL) ? 0 : 1);
2170#endif
2171 /* Make all the subdirectories */
2172 for (i = 0; i < n; i++) {
2173 tmpdir = pathJoin(dir, sarrayGetString(sa, i, L_NOCOPY));
2174#ifndef _WIN32
2175 ret += mkdir(tmpdir, 0777);
2176#else
2177 if (CreateDirectory(tmpdir, NULL) == 0)
2178 ret += (GetLastError () != ERROR_ALREADY_EXISTS);
2179#endif
2180 LEPT_FREE(dir);
2181 dir = tmpdir;
2182 }
2183 LEPT_FREE(dir);
2184 sarrayDestroy(&sa);
2185 if (ret > 0)
2186 L_ERROR("failure to create %d directories\n", __func__, ret);
2187 return ret;
2188}
2189
2190
2212l_int32
2213lept_rmdir(const char *subdir)
2214{
2215char *dir, *realdir, *fname, *fullname;
2216l_int32 exists, ret, i, nfiles;
2217SARRAY *sa;
2218#ifdef _WIN32
2219char *newpath;
2220#endif /* _WIN32 */
2221
2222 if (!subdir)
2223 return ERROR_INT("subdir not defined", __func__, 1);
2224 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2225 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
2226
2227 /* Find the temp subdirectory */
2228 dir = pathJoin("/tmp", subdir);
2229 if (!dir)
2230 return ERROR_INT("directory name not made", __func__, 1);
2231 lept_direxists(dir, &exists);
2232 if (!exists) { /* fail silently */
2233 LEPT_FREE(dir);
2234 return 0;
2235 }
2236
2237 /* List all the files in that directory */
2238 if ((sa = getFilenamesInDirectory(dir)) == NULL) {
2239 L_ERROR("directory %s does not exist!\n", __func__, dir);
2240 LEPT_FREE(dir);
2241 return 1;
2242 }
2243 nfiles = sarrayGetCount(sa);
2244
2245 for (i = 0; i < nfiles; i++) {
2246 fname = sarrayGetString(sa, i, L_NOCOPY);
2247 fullname = genPathname(dir, fname);
2248 remove(fullname);
2249 LEPT_FREE(fullname);
2250 }
2251
2252#ifndef _WIN32
2253 realdir = genPathname("/tmp", subdir);
2254 ret = rmdir(realdir);
2255 LEPT_FREE(realdir);
2256#else
2257 newpath = genPathname(dir, NULL);
2258 ret = (RemoveDirectory(newpath) ? 0 : 1);
2259 LEPT_FREE(newpath);
2260#endif /* !_WIN32 */
2261
2262 sarrayDestroy(&sa);
2263 LEPT_FREE(dir);
2264 return ret;
2265}
2266
2267
2284void
2285lept_direxists(const char *dir,
2286 l_int32 *pexists)
2287{
2288char *realdir;
2289
2290 if (!pexists) return;
2291 *pexists = 0;
2292 if (!dir) return;
2293 if ((realdir = genPathname(dir, NULL)) == NULL)
2294 return;
2295
2296#ifndef _WIN32
2297 {
2298 struct stat s;
2299 l_int32 err = stat(realdir, &s);
2300 if (err != -1 && S_ISDIR(s.st_mode))
2301 *pexists = 1;
2302 }
2303#else /* _WIN32 */
2304 {
2305 l_uint32 attributes;
2306 attributes = GetFileAttributes(realdir);
2307 if (attributes != INVALID_FILE_ATTRIBUTES &&
2308 (attributes & FILE_ATTRIBUTE_DIRECTORY))
2309 *pexists = 1;
2310 }
2311#endif /* _WIN32 */
2312
2313 LEPT_FREE(realdir);
2314}
2315
2316
2342l_int32
2343lept_rm_match(const char *subdir,
2344 const char *substr)
2345{
2346char *path, *fname;
2347char tempdir[256];
2348l_int32 i, n, ret;
2349SARRAY *sa;
2350
2351 makeTempDirname(tempdir, sizeof(tempdir), subdir);
2352 if ((sa = getSortedPathnamesInDirectory(tempdir, substr, 0, 0)) == NULL)
2353 return ERROR_INT("sa not made", __func__, -1);
2354 n = sarrayGetCount(sa);
2355 if (n == 0) {
2356 L_WARNING("no matching files found\n", __func__);
2357 sarrayDestroy(&sa);
2358 return 0;
2359 }
2360
2361 ret = 0;
2362 for (i = 0; i < n; i++) {
2363 fname = sarrayGetString(sa, i, L_NOCOPY);
2364 path = genPathname(fname, NULL);
2365 if (lept_rmfile(path) != 0) {
2366 L_ERROR("failed to remove %s\n", __func__, path);
2367 ret++;
2368 }
2369 LEPT_FREE(path);
2370 }
2371 sarrayDestroy(&sa);
2372 return ret;
2373}
2374
2375
2390l_int32
2391lept_rm(const char *subdir,
2392 const char *tail)
2393{
2394char *path;
2395char newtemp[256];
2396l_int32 ret;
2397
2398 if (!tail || strlen(tail) == 0)
2399 return ERROR_INT("tail undefined or empty", __func__, 1);
2400
2401 if (makeTempDirname(newtemp, sizeof(newtemp), subdir))
2402 return ERROR_INT("temp dirname not made", __func__, 1);
2403 path = genPathname(newtemp, tail);
2404 ret = lept_rmfile(path);
2405 LEPT_FREE(path);
2406 return ret;
2407}
2408
2409
2428l_int32
2429lept_rmfile(const char *filepath)
2430{
2431l_int32 ret;
2432
2433 if (!filepath || strlen(filepath) == 0)
2434 return ERROR_INT("filepath undefined or empty", __func__, 1);
2435
2436#ifndef _WIN32
2437 ret = remove(filepath);
2438#else
2439 /* Set attributes to allow deletion of read-only files */
2440 SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL);
2441 ret = DeleteFile(filepath) ? 0 : 1;
2442#endif /* !_WIN32 */
2443
2444 return ret;
2445}
2446
2447
2481l_int32
2482lept_mv(const char *srcfile,
2483 const char *newdir,
2484 const char *newtail,
2485 char **pnewpath)
2486{
2487char *srcpath, *newpath, *dir, *srctail;
2488char newtemp[256];
2489l_int32 ret;
2490
2491 if (!srcfile)
2492 return ERROR_INT("srcfile not defined", __func__, 1);
2493
2494 /* Require output pathname to be in /tmp/ or a subdirectory */
2495 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2496 return ERROR_INT("newdir not NULL or a subdir of /tmp", __func__, 1);
2497
2498 /* Get canonical src pathname */
2499 splitPathAtDirectory(srcfile, &dir, &srctail);
2500
2501#ifndef _WIN32
2502 srcpath = pathJoin(dir, srctail);
2503 LEPT_FREE(dir);
2504
2505 /* Generate output pathname */
2506 if (!newtail || newtail[0] == '\0')
2507 newpath = pathJoin(newtemp, srctail);
2508 else
2509 newpath = pathJoin(newtemp, newtail);
2510 LEPT_FREE(srctail);
2511
2512 /* Overwrite any existing file at 'newpath' */
2513 ret = fileCopy(srcpath, newpath);
2514 if (!ret) { /* and remove srcfile */
2515 char *realpath = genPathname(srcpath, NULL);
2516 remove(realpath);
2517 LEPT_FREE(realpath);
2518 }
2519#else
2520 srcpath = genPathname(dir, srctail);
2521 LEPT_FREE(dir);
2522
2523 /* Generate output pathname */
2524 if (!newtail || newtail[0] == '\0')
2525 newpath = genPathname(newtemp, srctail);
2526 else
2527 newpath = genPathname(newtemp, newtail);
2528 LEPT_FREE(srctail);
2529
2530 /* Overwrite any existing file at 'newpath' */
2531 ret = MoveFileEx(srcpath, newpath,
2532 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) ? 0 : 1;
2533#endif /* ! _WIN32 */
2534
2535 LEPT_FREE(srcpath);
2536 if (pnewpath)
2537 *pnewpath = newpath;
2538 else
2539 LEPT_FREE(newpath);
2540 return ret;
2541}
2542
2543
2578l_int32
2579lept_cp(const char *srcfile,
2580 const char *newdir,
2581 const char *newtail,
2582 char **pnewpath)
2583{
2584char *srcpath, *newpath, *dir, *srctail;
2585char newtemp[256];
2586l_int32 ret;
2587
2588 if (!srcfile)
2589 return ERROR_INT("srcfile not defined", __func__, 1);
2590
2591 /* Require output pathname to be in /tmp or a subdirectory */
2592 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2593 return ERROR_INT("newdir not NULL or a subdir of /tmp", __func__, 1);
2594
2595 /* Get canonical src pathname */
2596 splitPathAtDirectory(srcfile, &dir, &srctail);
2597
2598#ifndef _WIN32
2599 srcpath = pathJoin(dir, srctail);
2600 LEPT_FREE(dir);
2601
2602 /* Generate output pathname */
2603 if (!newtail || newtail[0] == '\0')
2604 newpath = pathJoin(newtemp, srctail);
2605 else
2606 newpath = pathJoin(newtemp, newtail);
2607 LEPT_FREE(srctail);
2608
2609 /* Overwrite any existing file at 'newpath' */
2610 ret = fileCopy(srcpath, newpath);
2611#else
2612 srcpath = genPathname(dir, srctail);
2613 LEPT_FREE(dir);
2614
2615 /* Generate output pathname */
2616 if (!newtail || newtail[0] == '\0')
2617 newpath = genPathname(newtemp, srctail);
2618 else
2619 newpath = genPathname(newtemp, newtail);
2620 LEPT_FREE(srctail);
2621
2622 /* Overwrite any existing file at 'newpath' */
2623 ret = CopyFile(srcpath, newpath, FALSE) ? 0 : 1;
2624#endif /* !_WIN32 */
2625
2626 LEPT_FREE(srcpath);
2627 if (pnewpath)
2628 *pnewpath = newpath;
2629 else
2630 LEPT_FREE(newpath);
2631 return ret;
2632}
2633
2634
2635/*--------------------------------------------------------------------*
2636 * Special debug/test function for calling 'system' *
2637 *--------------------------------------------------------------------*/
2638#if defined(__APPLE__)
2639 #include "TargetConditionals.h"
2640#endif /* __APPLE__ */
2641
2657void
2658callSystemDebug(const char *cmd)
2659{
2660l_int32 ret;
2661
2662 if (!cmd) {
2663 L_ERROR("cmd not defined\n", __func__);
2664 return;
2665 }
2666 if (LeptDebugOK == FALSE) {
2667 L_INFO("'system' calls are disabled\n", __func__);
2668 return;
2669 }
2670
2671#if defined(__APPLE__) /* iOS 11 does not support system() */
2672
2673 #if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) /* Mac OS X */
2674 ret = system(cmd);
2675 #elif TARGET_OS_IPHONE || defined(OS_IOS) /* iOS */
2676 L_ERROR("iOS 11 does not support system()\n", __func__);
2677 #endif /* TARGET_OS_OSX */
2678
2679#else /* ! __APPLE__ */
2680
2681 ret = system(cmd);
2682
2683#endif /* __APPLE__ */
2684}
2685
2686
2687/*--------------------------------------------------------------------*
2688 * General file name operations *
2689 *--------------------------------------------------------------------*/
2727l_ok
2728splitPathAtDirectory(const char *pathname,
2729 char **pdir,
2730 char **ptail)
2731{
2732char *cpathname, *lastslash;
2733
2734 if (!pdir && !ptail)
2735 return ERROR_INT("null input for both strings", __func__, 1);
2736 if (pdir) *pdir = NULL;
2737 if (ptail) *ptail = NULL;
2738 if (!pathname)
2739 return ERROR_INT("pathname not defined", __func__, 1);
2740
2741 cpathname = stringNew(pathname);
2742 convertSepCharsInPath(cpathname, UNIX_PATH_SEPCHAR);
2743 lastslash = strrchr(cpathname, '/');
2744 if (lastslash) {
2745 if (ptail)
2746 *ptail = stringNew(lastslash + 1);
2747 if (pdir) {
2748 *(lastslash + 1) = '\0';
2749 *pdir = cpathname;
2750 } else {
2751 LEPT_FREE(cpathname);
2752 }
2753 } else { /* no directory */
2754 if (pdir)
2755 *pdir = stringNew("");
2756 if (ptail)
2757 *ptail = cpathname;
2758 else
2759 LEPT_FREE(cpathname);
2760 }
2761
2762 return 0;
2763}
2764
2765
2795l_ok
2796splitPathAtExtension(const char *pathname,
2797 char **pbasename,
2798 char **pextension)
2799{
2800char *tail, *dir, *lastdot;
2801char empty[4] = "";
2802
2803 if (!pbasename && !pextension)
2804 return ERROR_INT("null input for both strings", __func__, 1);
2805 if (pbasename) *pbasename = NULL;
2806 if (pextension) *pextension = NULL;
2807 if (!pathname)
2808 return ERROR_INT("pathname not defined", __func__, 1);
2809
2810 /* Split out the directory first */
2811 splitPathAtDirectory(pathname, &dir, &tail);
2812
2813 /* Then look for a "." in the tail part.
2814 * This way we ignore all "." in the directory. */
2815 if ((lastdot = strrchr(tail, '.'))) {
2816 if (pextension)
2817 *pextension = stringNew(lastdot);
2818 if (pbasename) {
2819 *lastdot = '\0';
2820 *pbasename = stringJoin(dir, tail);
2821 }
2822 } else {
2823 if (pextension)
2824 *pextension = stringNew(empty);
2825 if (pbasename)
2826 *pbasename = stringNew(pathname);
2827 }
2828 LEPT_FREE(dir);
2829 LEPT_FREE(tail);
2830 return 0;
2831}
2832
2833
2872char *
2873pathJoin(const char *dir,
2874 const char *fname)
2875{
2876const char *slash = "/";
2877char *str, *dest;
2878l_int32 i, n1, n2, emptydir;
2879size_t size;
2880SARRAY *sa1, *sa2;
2881L_BYTEA *ba;
2882
2883 if (!dir && !fname)
2884 return stringNew("");
2885 if (dir && strlen(dir) >= 2 && dir[0] == '.' && dir[1] == '.')
2886 return (char *)ERROR_PTR("dir starts with '..'", __func__, NULL);
2887 if (fname && strlen(fname) >= 2 && fname[0] == '.' && fname[1] == '.')
2888 return (char *)ERROR_PTR("fname starts with '..'", __func__, NULL);
2889
2890 sa1 = sarrayCreate(0);
2891 sa2 = sarrayCreate(0);
2892 ba = l_byteaCreate(4);
2893
2894 /* Process %dir */
2895 if (dir && strlen(dir) > 0) {
2896 if (dir[0] == '/')
2897 l_byteaAppendString(ba, slash);
2898 sarraySplitString(sa1, dir, "/"); /* removes all slashes */
2899 n1 = sarrayGetCount(sa1);
2900 for (i = 0; i < n1; i++) {
2901 str = sarrayGetString(sa1, i, L_NOCOPY);
2902 l_byteaAppendString(ba, str);
2903 l_byteaAppendString(ba, slash);
2904 }
2905 }
2906
2907 /* Special case to add leading slash: dir NULL or empty string */
2908 emptydir = dir && strlen(dir) == 0;
2909 if ((!dir || emptydir) && fname && strlen(fname) > 0 && fname[0] == '/')
2910 l_byteaAppendString(ba, slash);
2911
2912 /* Process %fname */
2913 if (fname && strlen(fname) > 0) {
2914 sarraySplitString(sa2, fname, "/");
2915 n2 = sarrayGetCount(sa2);
2916 for (i = 0; i < n2; i++) {
2917 str = sarrayGetString(sa2, i, L_NOCOPY);
2918 l_byteaAppendString(ba, str);
2919 l_byteaAppendString(ba, slash);
2920 }
2921 }
2922
2923 /* Remove trailing slash */
2924 dest = (char *)l_byteaCopyData(ba, &size);
2925 if (size > 1 && dest[size - 1] == '/')
2926 dest[size - 1] = '\0';
2927
2928 sarrayDestroy(&sa1);
2929 sarrayDestroy(&sa2);
2930 l_byteaDestroy(&ba);
2931 return dest;
2932}
2933
2934
2949char *
2950appendSubdirs(const char *basedir,
2951 const char *subdirs)
2952{
2953char *newdir;
2954size_t len1, len2, len3, len4;
2955
2956 if (!basedir || !subdirs)
2957 return (char *)ERROR_PTR("basedir and subdirs not both defined",
2958 __func__, NULL);
2959
2960 len1 = strlen(basedir);
2961 len2 = strlen(subdirs);
2962 len3 = len1 + len2 + 8;
2963 if ((newdir = (char *)LEPT_CALLOC(len3, 1)) == NULL)
2964 return (char *)ERROR_PTR("newdir not made", __func__, NULL);
2965 stringCat(newdir, len3, basedir);
2966 if (newdir[len1 - 1] != '/') /* add '/' if necessary */
2967 newdir[len1] = '/';
2968 if (subdirs[0] == '/') /* add subdirs, stripping leading '/' */
2969 stringCat(newdir, len3, subdirs + 1);
2970 else
2971 stringCat(newdir, len3, subdirs);
2972 len4 = strlen(newdir);
2973 if (newdir[len4 - 1] == '/') /* strip trailing '/' */
2974 newdir[len4 - 1] = '\0';
2975
2976 return newdir;
2977}
2978
2979
2980/*--------------------------------------------------------------------*
2981 * Special file name operations *
2982 *--------------------------------------------------------------------*/
3003l_ok
3005 l_int32 type)
3006{
3007l_int32 i;
3008size_t len;
3009
3010 if (!path)
3011 return ERROR_INT("path not defined", __func__, 1);
3012 if (type != UNIX_PATH_SEPCHAR && type != WIN_PATH_SEPCHAR)
3013 return ERROR_INT("invalid type", __func__, 1);
3014
3015 len = strlen(path);
3016 if (type == UNIX_PATH_SEPCHAR) {
3017#ifdef _WIN32 /* only convert on Windows */
3018 for (i = 0; i < len; i++) {
3019 if (path[i] == '\\')
3020 path[i] = '/';
3021 }
3022#endif /* _WIN32 */
3023 } else { /* WIN_PATH_SEPCHAR */
3024 for (i = 0; i < len; i++) {
3025 if (path[i] == '/')
3026 path[i] = '\\';
3027 }
3028 }
3029 return 0;
3030}
3031
3032
3067char *
3068genPathname(const char *dir,
3069 const char *fname)
3070{
3071l_int32 is_win32 = FALSE;
3072char *cdir, *pathout;
3073l_int32 dirlen, namelen;
3074size_t size;
3075
3076 if (!dir && !fname)
3077 return (char *)ERROR_PTR("no input", __func__, NULL);
3078
3079 /* Handle the case where we start from the current directory */
3080 if (!dir || dir[0] == '\0') {
3081 if ((cdir = getcwd(NULL, 0)) == NULL)
3082 return (char *)ERROR_PTR("no current dir found", __func__, NULL);
3083 } else {
3084 cdir = stringNew(dir);
3085 }
3086
3087 /* Convert to unix path separators, and remove the trailing
3088 * slash in the directory, except when dir == "/" */
3089 convertSepCharsInPath(cdir, UNIX_PATH_SEPCHAR);
3090 dirlen = strlen(cdir);
3091 if (cdir[dirlen - 1] == '/' && dirlen != 1) {
3092 cdir[dirlen - 1] = '\0';
3093 dirlen--;
3094 }
3095
3096 namelen = (fname) ? strlen(fname) : 0;
3097 size = dirlen + namelen + 256;
3098 if ((pathout = (char *)LEPT_CALLOC(size, sizeof(char))) == NULL) {
3099 LEPT_FREE(cdir);
3100 return (char *)ERROR_PTR("pathout not made", __func__, NULL);
3101 }
3102
3103#ifdef _WIN32
3104 is_win32 = TRUE;
3105#endif /* _WIN32 */
3106
3107 /* First handle %dir (which may be a full pathname).
3108 * There is no path rewriting on unix, and on win32, we do not
3109 * rewrite unless the specified directory is /tmp or
3110 * a subdirectory of /tmp */
3111 if (!is_win32 || dirlen < 4 ||
3112 (dirlen == 4 && strncmp(cdir, "/tmp", 4) != 0) || /* not in "/tmp" */
3113 (dirlen > 4 && strncmp(cdir, "/tmp/", 5) != 0)) { /* not in "/tmp/" */
3114 stringCopy(pathout, cdir, dirlen);
3115 } else { /* Rewrite for win32 with "/tmp" specified for the directory. */
3116#ifdef _WIN32
3117 l_int32 tmpdirlen;
3118 char tmpdir[MAX_PATH];
3119 GetTempPath(sizeof(tmpdir), tmpdir); /* get the Windows temp dir */
3120 tmpdirlen = strlen(tmpdir);
3121 if (tmpdirlen > 0 && tmpdir[tmpdirlen - 1] == '\\') {
3122 tmpdir[tmpdirlen - 1] = '\0'; /* trim the trailing '\' */
3123 }
3124 tmpdirlen = strlen(tmpdir);
3125 stringCopy(pathout, tmpdir, tmpdirlen);
3126
3127 /* Add the rest of cdir */
3128 if (dirlen > 4)
3129 stringCat(pathout, size, cdir + 4);
3130#endif /* _WIN32 */
3131 }
3132
3133 /* Now handle %fname */
3134 if (fname && strlen(fname) > 0) {
3135 dirlen = strlen(pathout);
3136 pathout[dirlen] = '/';
3137 stringCat(pathout, size, fname);
3138 }
3139
3140 LEPT_FREE(cdir);
3141 return pathout;
3142}
3143
3144
3174l_ok
3175makeTempDirname(char *result,
3176 size_t nbytes,
3177 const char *subdir)
3178{
3179char *dir, *path;
3180l_int32 ret = 0;
3181size_t pathlen;
3182
3183 if (!result)
3184 return ERROR_INT("result not defined", __func__, 1);
3185 if (subdir && ((subdir[0] == '.') || (subdir[0] == '/')))
3186 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
3187
3188 memset(result, 0, nbytes);
3189
3190#ifdef __APPLE__
3191 {
3192 size_t n = confstr(_CS_DARWIN_USER_TEMP_DIR, result, nbytes);
3193 if (n == 0) {
3194 L_ERROR("failed to find tmp dir, %s\n", __func__, strerror(errno));
3195 return 1;
3196 } else if (n > nbytes) {
3197 return ERROR_INT("result array too small for path\n", __func__, 1);
3198 }
3199 dir = pathJoin(result, subdir);
3200 }
3201#else
3202 dir = pathJoin("/tmp", subdir);
3203#endif /* ~ __APPLE__ */
3204
3205#ifndef _WIN32
3206 path = stringNew(dir);
3207#else
3208 path = genPathname(dir, NULL);
3209#endif /* ~ _WIN32 */
3210 pathlen = strlen(path);
3211 if (pathlen < nbytes - 1) {
3212 stringCopy(result, path, nbytes);
3213 } else {
3214 L_ERROR("result array too small for path\n", __func__);
3215 ret = 1;
3216 }
3217
3218 LEPT_FREE(dir);
3219 LEPT_FREE(path);
3220 return ret;
3221}
3222
3223
3237l_ok
3239 size_t nbytes,
3240 l_int32 flag)
3241{
3242char lastchar;
3243size_t len;
3244
3245 if (!path)
3246 return ERROR_INT("path not defined", __func__, 1);
3247 if (flag != L_ADD_TRAIL_SLASH && flag != L_REMOVE_TRAIL_SLASH)
3248 return ERROR_INT("invalid flag", __func__, 1);
3249
3250 len = strlen(path);
3251 lastchar = path[len - 1];
3252 if (flag == L_ADD_TRAIL_SLASH && lastchar != '/' && len < nbytes - 2) {
3253 path[len] = '/';
3254 path[len + 1] = '\0';
3255 } else if (flag == L_REMOVE_TRAIL_SLASH && lastchar == '/') {
3256 path[len - 1] = '\0';
3257 }
3258 return 0;
3259}
3260
3261
3285char *
3287{
3288char dirname[240];
3289
3290 if (makeTempDirname(dirname, sizeof(dirname), NULL) == 1)
3291 return (char *)ERROR_PTR("failed to make dirname", __func__, NULL);
3292
3293#ifndef _WIN32
3294{
3295 char *pattern;
3296 l_int32 fd;
3297 pattern = stringConcatNew(dirname, "/lept.XXXXXX", NULL);
3298 fd = mkstemp(pattern);
3299 if (fd == -1) {
3300 LEPT_FREE(pattern);
3301 return (char *)ERROR_PTR("mkstemp failed", __func__, NULL);
3302 }
3303 close(fd);
3304 return pattern;
3305}
3306#else
3307{
3308 char fname[MAX_PATH];
3309 FILE *fp;
3310 if (GetTempFileName(dirname, "lp.", 0, fname) == 0)
3311 return (char *)ERROR_PTR("GetTempFileName failed", __func__, NULL);
3312 if ((fp = fopen(fname, "wb")) == NULL)
3313 return (char *)ERROR_PTR("file cannot be written to", __func__, NULL);
3314 fclose(fp);
3315 return stringNew(fname);
3316}
3317#endif /* ~ _WIN32 */
3318}
3319
3320
3339l_int32
3341 l_int32 numpre,
3342 l_int32 numpost)
3343{
3344char *tail, *basename;
3345l_int32 len, nret, num;
3346
3347 if (!fname)
3348 return ERROR_INT("fname not defined", __func__, -1);
3349
3350 splitPathAtDirectory(fname, NULL, &tail);
3351 splitPathAtExtension(tail, &basename, NULL);
3352 LEPT_FREE(tail);
3353
3354 len = strlen(basename);
3355 if (numpre + numpost > len - 1) {
3356 LEPT_FREE(basename);
3357 return ERROR_INT("numpre + numpost too big", __func__, -1);
3358 }
3359
3360 basename[len - numpost] = '\0';
3361 nret = sscanf(basename + numpre, "%d", &num);
3362 LEPT_FREE(basename);
3363
3364 if (nret == 1)
3365 return num;
3366 else
3367 return -1; /* not found */
3368}
struct L_Dna L_DNA
Definition array.h:72
struct Numa NUMA
Definition array.h:66
struct L_Bytea L_BYTEA
Definition array.h:84
struct Sarray SARRAY
Definition array.h:81
@ L_NOCOPY
Definition pix.h:503
@ L_ADD_TRAIL_SLASH
Definition pix.h:1081
@ L_REMOVE_TRAIL_SLASH
Definition pix.h:1082
l_int32 n
Definition bbuffer.h:53
l_int32 nalloc
Definition bbuffer.h:52
l_uint8 * array
Definition bbuffer.h:55
l_int32 stringLength(const char *src, size_t size)
stringLength()
Definition utils2.c:373
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition utils2.c:1559
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition utils2.c:2213
char * stringCopySegment(const char *src, l_int32 start, l_int32 nbytes)
stringCopySegment()
Definition utils2.c:301
void lept_direxists(const char *dir, l_int32 *pexists)
lept_direxists()
Definition utils2.c:2285
l_int32 lept_rm(const char *subdir, const char *tail)
lept_rm()
Definition utils2.c:2391
l_ok lept_fclose(FILE *fp)
lept_fclose()
Definition utils2.c:2065
char * stringReverse(const char *src)
stringReverse()
Definition utils2.c:581
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition utils2.c:2429
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition utils2.c:1981
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition utils2.c:2873
l_uint8 * l_binaryCopy(const l_uint8 *datas, size_t size)
l_binaryCopy()
Definition utils2.c:1619
l_uint8 * l_binaryReadSelectStream(FILE *fp, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelectStream()
Definition utils2.c:1466
l_ok fileAppendString(const char *filename, const char *str)
fileAppendString()
Definition utils2.c:1741
l_int32 lept_rm_match(const char *subdir, const char *substr)
lept_rm_match()
Definition utils2.c:2343
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition utils2.c:339
char * strtokSafe(char *cstr, const char *seps, char **psaveptr)
strtokSafe()
Definition utils2.c:631
l_ok fileConcatenate(const char *srcfile, const char *destfile)
fileConcatenate()
Definition utils2.c:1715
l_ok stringJoinIP(char **psrc1, const char *src2)
stringJoinIP()
Definition utils2.c:559
char * stringRemoveChars(const char *src, const char *remchars)
stringRemoveChars()
Definition utils2.c:798
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition utils2.c:1905
void lept_free(void *ptr)
lept_free()
Definition utils2.c:2110
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition utils2.c:3286
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition utils2.c:3238
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition utils2.c:2796
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition utils2.c:3068
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition utils2.c:2658
l_int32 lept_cp(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_cp()
Definition utils2.c:2579
l_int32 lept_mv(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_mv()
Definition utils2.c:2482
l_ok stringCheckForChars(const char *src, const char *chars, l_int32 *pfound)
stringCheckForChars()
Definition utils2.c:765
FILE * lept_fopen(const char *filename, const char *mode)
lept_fopen()
Definition utils2.c:2037
char * stringReplaceEachSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *pcount)
stringReplaceEachSubstr()
Definition utils2.c:852
char * stringConcatNew(const char *first,...)
stringConcatNew()
Definition utils2.c:459
l_ok l_binaryCompare(const l_uint8 *data1, size_t size1, const l_uint8 *data2, size_t size2, l_int32 *psame)
l_binaryCompare()
Definition utils2.c:1653
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition utils2.c:1581
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition utils2.c:2728
l_uint8 * l_binaryReadSelect(const char *filename, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelect()
Definition utils2.c:1423
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition utils2.c:1310
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition utils2.c:1937
l_int32 stringFindSubstr(const char *src, const char *sub, l_int32 *ploc)
stringFindSubstr()
Definition utils2.c:995
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition utils2.c:506
l_ok convertSepCharsInPath(char *path, l_int32 type)
convertSepCharsInPath()
Definition utils2.c:3004
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition utils2.c:413
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition utils2.c:1864
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition utils2.c:1358
char * stringReplaceSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *ploc, l_int32 *pfound)
stringReplaceSubstr()
Definition utils2.c:907
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition utils2.c:1262
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition utils2.c:2138
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition utils2.c:1137
l_uint8 * arrayReplaceEachSequence(const l_uint8 *datas, size_t dataslen, const l_uint8 *seq, size_t seqlen, const l_uint8 *newseq, size_t newseqlen, size_t *pdatadlen, l_int32 *pcount)
arrayReplaceEachSequence()
Definition utils2.c:1048
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition utils2.c:1519
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition utils2.c:3175
l_ok stringSplitOnToken(char *cstr, const char *seps, char **phead, char **ptail)
stringSplitOnToken()
Definition utils2.c:723
void * lept_calloc(size_t nmemb, size_t size)
lept_calloc()
Definition utils2.c:2089
L_DNA * stringFindEachSubstr(const char *src, const char *sub)
stringFindEachSubstr()
Definition utils2.c:966
char * stringNew(const char *src)
stringNew()
Definition utils2.c:223
l_ok stringCopy(char *dest, const char *src, l_int32 n)
stringCopy()
Definition utils2.c:261
l_ok fileSplitLinesUniform(const char *filename, l_int32 n, l_int32 save_empty, const char *rootpath, const char *ext)
fileSplitLinesUniform()
Definition utils2.c:1789
l_int32 extractNumberFromFilename(const char *fname, l_int32 numpre, l_int32 numpost)
extractNumberFromFilename()
Definition utils2.c:3340
char * appendSubdirs(const char *basedir, const char *subdirs)
appendSubdirs()
Definition utils2.c:2950
l_ok arrayFindSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen, l_int32 *poffset, l_int32 *pfound)
arrayFindSequence()
Definition utils2.c:1195
l_ok fileCopy(const char *srcfile, const char *newfile)
fileCopy()
Definition utils2.c:1687