Leptonica 1.85.0
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
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#if defined(__APPLE__) || defined(_WIN32)
213/* Rewrite paths starting with /tmp for macOS, iOS and Windows. */
214#define REWRITE_TMP
215#endif
216
217/*--------------------------------------------------------------------*
218 * Safe string operations *
219 *--------------------------------------------------------------------*/
226char *
227stringNew(const char *src)
228{
229l_int32 len;
230char *dest;
231
232 if (!src) {
233 L_WARNING("src not defined\n", __func__);
234 return NULL;
235 }
236
237 len = strlen(src);
238 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
239 return (char *)ERROR_PTR("dest not made", __func__, NULL);
240
241 stringCopy(dest, src, len);
242 return dest;
243}
244
245
264l_ok
265stringCopy(char *dest,
266 const char *src,
267 l_int32 n)
268{
269l_int32 i;
270
271 if (!dest)
272 return ERROR_INT("dest not defined", __func__, 1);
273 if (!src || n < 1)
274 return 0;
275
276 /* Implementation of strncpy that valgrind doesn't complain about */
277 for (i = 0; i < n && src[i] != '\0'; i++)
278 dest[i] = src[i];
279 for (; i < n; i++)
280 dest[i] = '\0';
281 return 0;
282}
283
284
304char *
305stringCopySegment(const char *src,
306 l_int32 start,
307 l_int32 nbytes)
308{
309char *dest;
310l_int32 len;
311
312 if (!src)
313 return (char *)ERROR_PTR("src not defined", __func__, NULL);
314 len = strlen(src);
315 if (start < 0 || start > len - 1)
316 return (char *)ERROR_PTR("invalid start", __func__, NULL);
317 if (nbytes <= 0) /* copy to the end */
318 nbytes = len - start;
319 if (start + nbytes > len) /* truncate to the end */
320 nbytes = len - start;
321 if ((dest = (char *)LEPT_CALLOC(nbytes + 1, sizeof(char))) == NULL)
322 return (char *)ERROR_PTR("dest not made", __func__, NULL);
323 stringCopy(dest, src + start, nbytes);
324 return dest;
325}
326
327
342l_ok
343stringReplace(char **pdest,
344 const char *src)
345{
346 if (!pdest)
347 return ERROR_INT("pdest not defined", __func__, 1);
348
349 if (*pdest)
350 LEPT_FREE(*pdest);
351
352 if (src)
353 *pdest = stringNew(src);
354 else
355 *pdest = NULL;
356 return 0;
357}
358
359
377l_int32
378stringLength(const char *src,
379 size_t size)
380{
381l_int32 i;
382
383 if (!src)
384 return 0;
385 if (size < 1)
386 return ERROR_INT("size < 1; too small", __func__, 0);
387
388 for (i = 0; i < size; i++) {
389 if (src[i] == '\0')
390 return i;
391 }
392
393 /* Didn't find a NUL byte */
394 L_ERROR("NUL byte not found in %zu bytes\n", __func__, size);
395 return size;
396}
397
398
420l_int32
421stringCat(char *dest,
422 size_t size,
423 const char *src)
424{
425l_int32 i, n;
426l_int32 lendest, lensrc;
427
428 if (!dest)
429 return ERROR_INT("dest not defined", __func__, -1);
430 if (size < 1)
431 return ERROR_INT("size < 1; too small", __func__, -1);
432 if (!src)
433 return 0;
434
435 lendest = stringLength(dest, size);
436 if (lendest == size)
437 return ERROR_INT("no terminating nul byte", __func__, -1);
438 lensrc = stringLength(src, size);
439 if (lensrc == 0)
440 return 0; /* nothing added to dest */
441 n = (lendest + lensrc > size - 1) ? 0 : lensrc;
442 if (n == 0)
443 return ERROR_INT("dest too small for append", __func__, -1);
444
445 for (i = 0; i < n; i++)
446 dest[lendest + i] = src[i];
447 dest[lendest + n] = '\0';
448 return n;
449}
450
451
466char *
467stringConcatNew(const char *first, ...)
468{
469size_t len;
470char *result, *ptr;
471const char *arg;
472va_list args;
473
474 if (!first) return NULL;
475
476 /* Find the length of the output string */
477 va_start(args, first);
478 len = strlen(first);
479 while ((arg = va_arg(args, const char *)) != NULL)
480 len += strlen(arg);
481 va_end(args);
482 result = (char *)LEPT_CALLOC(len + 1, sizeof(char));
483
484 /* Concatenate the args */
485 va_start(args, first);
486 ptr = result;
487 arg = first;
488 while (*arg)
489 *ptr++ = *arg++;
490 while ((arg = va_arg(args, const char *)) != NULL) {
491 while (*arg)
492 *ptr++ = *arg++;
493 }
494 va_end(args);
495 return result;
496}
497
498
513char *
514stringJoin(const char *src1,
515 const char *src2)
516{
517char *dest;
518l_int32 srclen1, srclen2, destlen;
519
520 srclen1 = (src1) ? strlen(src1) : 0;
521 srclen2 = (src2) ? strlen(src2) : 0;
522 destlen = srclen1 + srclen2 + 3;
523
524 if ((dest = (char *)LEPT_CALLOC(destlen, sizeof(char))) == NULL)
525 return (char *)ERROR_PTR("calloc fail for dest", __func__, NULL);
526
527 if (src1)
528 stringCat(dest, destlen, src1);
529 if (src2)
530 stringCat(dest, destlen, src2);
531 return dest;
532}
533
534
566l_ok
567stringJoinIP(char **psrc1,
568 const char *src2)
569{
570char *tmpstr;
571
572 if (!psrc1)
573 return ERROR_INT("&src1 not defined", __func__, 1);
574
575 tmpstr = stringJoin(*psrc1, src2);
576 LEPT_FREE(*psrc1);
577 *psrc1 = tmpstr;
578 return 0;
579}
580
581
588char *
589stringReverse(const char *src)
590{
591char *dest;
592l_int32 i, len;
593
594 if (!src)
595 return (char *)ERROR_PTR("src not defined", __func__, NULL);
596 len = strlen(src);
597 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
598 return (char *)ERROR_PTR("calloc fail for dest", __func__, NULL);
599 for (i = 0; i < len; i++)
600 dest[i] = src[len - 1 - i];
601
602 return dest;
603}
604
605
638char *
639strtokSafe(char *cstr,
640 const char *seps,
641 char **psaveptr)
642{
643char nextc;
644char *start, *substr;
645l_int32 istart, i, j, nchars;
646
647 if (!seps)
648 return (char *)ERROR_PTR("seps not defined", __func__, NULL);
649 if (!psaveptr)
650 return (char *)ERROR_PTR("&saveptr not defined", __func__, NULL);
651
652 if (!cstr) {
653 start = *psaveptr;
654 } else {
655 start = cstr;
656 *psaveptr = NULL;
657 }
658 if (!start) /* nothing to do */
659 return NULL;
660
661 /* First time, scan for the first non-sep character */
662 istart = 0;
663 if (cstr) {
664 for (istart = 0;; istart++) {
665 if ((nextc = start[istart]) == '\0') {
666 *psaveptr = NULL; /* in case caller doesn't check ret value */
667 return NULL;
668 }
669 if (!strchr(seps, nextc))
670 break;
671 }
672 }
673
674 /* Scan through, looking for a sep character; if none is
675 * found, 'i' will be at the end of the string. */
676 for (i = istart;; i++) {
677 if ((nextc = start[i]) == '\0')
678 break;
679 if (strchr(seps, nextc))
680 break;
681 }
682
683 /* Save the substring */
684 nchars = i - istart;
685 substr = (char *)LEPT_CALLOC(nchars + 1, sizeof(char));
686 stringCopy(substr, start + istart, nchars);
687
688 /* Look for the next non-sep character.
689 * If this is the last substring, return a null saveptr. */
690 for (j = i;; j++) {
691 if ((nextc = start[j]) == '\0') {
692 *psaveptr = NULL; /* no more non-sep characters */
693 break;
694 }
695 if (!strchr(seps, nextc)) {
696 *psaveptr = start + j; /* start here on next call */
697 break;
698 }
699 }
700
701 return substr;
702}
703
704
730l_ok
732 const char *seps,
733 char **phead,
734 char **ptail)
735{
736char *saveptr;
737
738 if (!phead)
739 return ERROR_INT("&head not defined", __func__, 1);
740 if (!ptail)
741 return ERROR_INT("&tail not defined", __func__, 1);
742 *phead = *ptail = NULL;
743 if (!cstr)
744 return ERROR_INT("cstr not defined", __func__, 1);
745 if (!seps)
746 return ERROR_INT("seps not defined", __func__, 1);
747
748 *phead = strtokSafe(cstr, seps, &saveptr);
749 if (saveptr)
750 *ptail = stringNew(saveptr);
751 return 0;
752}
753
754
755/*--------------------------------------------------------------------*
756 * Find and replace procs *
757 *--------------------------------------------------------------------*/
772l_ok
773stringCheckForChars(const char *src,
774 const char *chars,
775 l_int32 *pfound)
776{
777char ch;
778l_int32 i, n;
779
780 if (!pfound)
781 return ERROR_INT("&found not defined", __func__, 1);
782 *pfound = FALSE;
783 if (!src || !chars)
784 return ERROR_INT("src and chars not both defined", __func__, 1);
785
786 n = strlen(src);
787 for (i = 0; i < n; i++) {
788 ch = src[i];
789 if (strchr(chars, ch)) {
790 *pfound = TRUE;
791 break;
792 }
793 }
794 return 0;
795}
796
797
805char *
806stringRemoveChars(const char *src,
807 const char *remchars)
808{
809char ch;
810char *dest;
811l_int32 nsrc, i, k;
812
813 if (!src)
814 return (char *)ERROR_PTR("src not defined", __func__, NULL);
815 if (!remchars)
816 return stringNew(src);
817
818 if ((dest = (char *)LEPT_CALLOC(strlen(src) + 1, sizeof(char))) == NULL)
819 return (char *)ERROR_PTR("dest not made", __func__, NULL);
820 nsrc = strlen(src);
821 for (i = 0, k = 0; i < nsrc; i++) {
822 ch = src[i];
823 if (!strchr(remchars, ch))
824 dest[k++] = ch;
825 }
826
827 return dest;
828}
829
830
859char *
861 const char *sub1,
862 const char *sub2,
863 l_int32 *pcount)
864{
865size_t datalen;
866
867 if (pcount) *pcount = 0;
868 if (!src || !sub1 || !sub2)
869 return (char *)ERROR_PTR("src, sub1, sub2 not all defined",
870 __func__, NULL);
871
872 if (strlen(sub2) > 0) {
873 return (char *)arrayReplaceEachSequence(
874 (const l_uint8 *)src, strlen(src),
875 (const l_uint8 *)sub1, strlen(sub1),
876 (const l_uint8 *)sub2, strlen(sub2),
877 &datalen, pcount);
878 } else { /* empty replacement string; removal only */
879 return (char *)arrayReplaceEachSequence(
880 (const l_uint8 *)src, strlen(src),
881 (const l_uint8 *)sub1, strlen(sub1),
882 NULL, 0, &datalen, pcount);
883 }
884}
885
886
914char *
915stringReplaceSubstr(const char *src,
916 const char *sub1,
917 const char *sub2,
918 l_int32 *ploc,
919 l_int32 *pfound)
920{
921const char *ptr;
922char *dest;
923l_int32 nsrc, nsub1, nsub2, len, npre, loc;
924
925 if (pfound) *pfound = 0;
926 if (!src || !sub1 || !sub2)
927 return (char *)ERROR_PTR("src, sub1, sub2 not all defined",
928 __func__, NULL);
929
930 if (ploc)
931 loc = *ploc;
932 else
933 loc = 0;
934 if (!strcmp(sub1, sub2))
935 return stringNew(src);
936 if ((ptr = strstr(src + loc, sub1)) == NULL)
937 return stringNew(src);
938 if (pfound) *pfound = 1;
939
940 nsrc = strlen(src);
941 nsub1 = strlen(sub1);
942 nsub2 = strlen(sub2);
943 len = nsrc + nsub2 - nsub1;
944 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
945 return (char *)ERROR_PTR("dest not made", __func__, NULL);
946 npre = ptr - src;
947 memcpy(dest, src, npre);
948 strcpy(dest + npre, sub2);
949 strcpy(dest + npre + nsub2, ptr + nsub1);
950 if (ploc) *ploc = npre + nsub2;
951 return dest;
952}
953
954
973L_DNA *
974stringFindEachSubstr(const char *src,
975 const char *sub)
976{
977 if (!src || !sub)
978 return (L_DNA *)ERROR_PTR("src, sub not both defined", __func__, NULL);
979
980 return arrayFindEachSequence((const l_uint8 *)src, strlen(src),
981 (const l_uint8 *)sub, strlen(sub));
982}
983
984
1002l_int32
1003stringFindSubstr(const char *src,
1004 const char *sub,
1005 l_int32 *ploc)
1006{
1007const char *ptr;
1008
1009 if (ploc) *ploc = -1;
1010 if (!src || !sub)
1011 return ERROR_INT("src and sub not both defined", __func__, 0);
1012 if (strlen(sub) == 0)
1013 return ERROR_INT("substring length 0", __func__, 0);
1014 if (strlen(src) == 0)
1015 return 0;
1016
1017 if ((ptr = strstr(src, sub)) == NULL) /* not found */
1018 return 0;
1019
1020 if (ploc)
1021 *ploc = ptr - src;
1022 return 1;
1023}
1024
1025
1055l_uint8 *
1056arrayReplaceEachSequence(const l_uint8 *datas,
1057 size_t dataslen,
1058 const l_uint8 *seq,
1059 size_t seqlen,
1060 const l_uint8 *newseq,
1061 size_t newseqlen,
1062 size_t *pdatadlen,
1063 l_int32 *pcount)
1064{
1065l_uint8 *datad;
1066size_t newsize;
1067l_int32 n, i, j, di, si, index, incr;
1068L_DNA *da;
1069
1070 if (pcount) *pcount = 0;
1071 if (!datas || !seq)
1072 return (l_uint8 *)ERROR_PTR("datas & seq not both defined",
1073 __func__, NULL);
1074 if (!pdatadlen)
1075 return (l_uint8 *)ERROR_PTR("&datadlen not defined", __func__, NULL);
1076 *pdatadlen = 0;
1077
1078 /* Identify the locations of the sequence. If there are none,
1079 * return a copy of %datas. */
1080 if ((da = arrayFindEachSequence(datas, dataslen, seq, seqlen)) == NULL) {
1081 *pdatadlen = dataslen;
1082 return l_binaryCopy(datas, dataslen);
1083 }
1084
1085 /* Allocate the output data; insure null termination */
1086 n = l_dnaGetCount(da);
1087 if (pcount) *pcount = n;
1088 if (!newseq) newseqlen = 0;
1089 newsize = dataslen + n * (newseqlen - seqlen) + 4;
1090 if ((datad = (l_uint8 *)LEPT_CALLOC(newsize, sizeof(l_uint8))) == NULL) {
1091 l_dnaDestroy(&da);
1092 return (l_uint8 *)ERROR_PTR("datad not made", __func__, NULL);
1093 }
1094
1095 /* Replace each sequence instance with a new sequence */
1096 l_dnaGetIValue(da, 0, &si);
1097 for (i = 0, di = 0, index = 0; i < dataslen; i++) {
1098 if (i == si) {
1099 index++;
1100 if (index < n) {
1101 l_dnaGetIValue(da, index, &si);
1102 incr = L_MIN(seqlen, si - i); /* amount to remove from datas */
1103 } else {
1104 incr = seqlen;
1105 }
1106 i += incr - 1; /* jump over the matched sequence in datas */
1107 if (newseq) { /* add new sequence to datad */
1108 for (j = 0; j < newseqlen; j++)
1109 datad[di++] = newseq[j];
1110 }
1111 } else {
1112 datad[di++] = datas[i];
1113 }
1114 }
1115
1116 *pdatadlen = di;
1117 l_dnaDestroy(&da);
1118 return datad;
1119}
1120
1121
1144L_DNA *
1145arrayFindEachSequence(const l_uint8 *data,
1146 size_t datalen,
1147 const l_uint8 *sequence,
1148 size_t seqlen)
1149{
1150l_int32 start, offset, realoffset, found;
1151L_DNA *da;
1152
1153 if (!data || !sequence)
1154 return (L_DNA *)ERROR_PTR("data & sequence not both defined",
1155 __func__, NULL);
1156
1157 da = l_dnaCreate(0);
1158 start = 0;
1159 while (1) {
1160 arrayFindSequence(data + start, datalen - start, sequence, seqlen,
1161 &offset, &found);
1162 if (found == FALSE)
1163 break;
1164
1165 realoffset = start + offset;
1166 l_dnaAddNumber(da, realoffset);
1167 start = realoffset + seqlen;
1168 if (start >= datalen)
1169 break;
1170 }
1171
1172 if (l_dnaGetCount(da) == 0)
1173 l_dnaDestroy(&da);
1174 return da;
1175}
1176
1177
1204l_ok
1205arrayFindSequence(const l_uint8 *data,
1206 size_t datalen,
1207 const l_uint8 *sequence,
1208 size_t seqlen,
1209 l_int32 *poffset,
1210 l_int32 *pfound)
1211{
1212l_int32 i, j, found, lastpos;
1213
1214 if (poffset) *poffset = 0;
1215 if (pfound) *pfound = FALSE;
1216 if (!data || !sequence)
1217 return ERROR_INT("data & sequence not both defined", __func__, 1);
1218 if (!poffset || !pfound)
1219 return ERROR_INT("&offset and &found not defined", __func__, 1);
1220
1221 lastpos = datalen - seqlen + 1;
1222 found = FALSE;
1223 for (i = 0; i < lastpos; i++) {
1224 for (j = 0; j < seqlen; j++) {
1225 if (data[i + j] != sequence[j])
1226 break;
1227 if (j == seqlen - 1)
1228 found = TRUE;
1229 }
1230 if (found == TRUE)
1231 break;
1232 }
1233
1234 if (found == TRUE) {
1235 *poffset = i;
1236 *pfound = TRUE;
1237 }
1238 return 0;
1239}
1240
1241
1242/*--------------------------------------------------------------------*
1243 * Safe realloc *
1244 *--------------------------------------------------------------------*/
1271void *
1272reallocNew(void **pindata,
1273 size_t oldsize,
1274 size_t newsize)
1275{
1276size_t minsize;
1277void *indata;
1278void *newdata;
1279
1280 if (!pindata)
1281 return ERROR_PTR("input data not defined", __func__, NULL);
1282 indata = *pindata;
1283
1284 if (newsize == 0) { /* nonstandard usage */
1285 if (indata) {
1286 LEPT_FREE(indata);
1287 *pindata = NULL;
1288 }
1289 return NULL;
1290 }
1291
1292 if (!indata) { /* nonstandard usage */
1293 if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1294 return ERROR_PTR("newdata not made", __func__, NULL);
1295 return newdata;
1296 }
1297
1298 /* Standard usage */
1299 if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1300 return ERROR_PTR("newdata not made", __func__, NULL);
1301 minsize = L_MIN(oldsize, newsize);
1302 memcpy(newdata, indata, minsize);
1303 LEPT_FREE(indata);
1304 *pindata = NULL;
1305 return newdata;
1306}
1307
1308
1309/*--------------------------------------------------------------------*
1310 * Read and write between file and memory *
1311 *--------------------------------------------------------------------*/
1319l_uint8 *
1320l_binaryRead(const char *filename,
1321 size_t *pnbytes)
1322{
1323l_uint8 *data;
1324FILE *fp;
1325
1326 if (!pnbytes)
1327 return (l_uint8 *)ERROR_PTR("pnbytes not defined", __func__, NULL);
1328 *pnbytes = 0;
1329 if (!filename)
1330 return (l_uint8 *)ERROR_PTR("filename not defined", __func__, NULL);
1331
1332 if ((fp = fopenReadStream(filename)) == NULL)
1333 return (l_uint8 *)ERROR_PTR_1("file stream not opened",
1334 filename, __func__, NULL);
1335 data = l_binaryReadStream(fp, pnbytes);
1336 fclose(fp);
1337 return data;
1338}
1339
1340
1368l_uint8 *
1370 size_t *pnbytes)
1371{
1372l_uint8 *data;
1373l_int32 seekable, navail, nadd, nread;
1374L_BBUFFER *bb;
1375
1376 if (!pnbytes)
1377 return (l_uint8 *)ERROR_PTR("&nbytes not defined", __func__, NULL);
1378 *pnbytes = 0;
1379 if (!fp)
1380 return (l_uint8 *)ERROR_PTR("fp not defined", __func__, NULL);
1381
1382 /* Test if the stream is seekable, by attempting to seek to
1383 * the start of data. This is a no-op. If it is seekable, use
1384 * l_binaryReadSelectStream() to determine the size of the
1385 * data to be read in advance. */
1386 seekable = (ftell(fp) == 0) ? 1 : 0;
1387 if (seekable)
1388 return l_binaryReadSelectStream(fp, 0, 0, pnbytes);
1389
1390 /* If it is not seekable, use the bbuffer to realloc memory
1391 * as needed during reading. */
1392 bb = bbufferCreate(NULL, 4096);
1393 while (1) {
1394 navail = bb->nalloc - bb->n;
1395 if (navail < 4096) {
1396 nadd = L_MAX(bb->nalloc, 4096);
1397 bbufferExtendArray(bb, nadd);
1398 }
1399 nread = fread((void *)(bb->array + bb->n), 1, 4096, fp);
1400 bb->n += nread;
1401 if (nread != 4096) break;
1402 }
1403
1404 /* Copy the data to a new array sized for the data, because
1405 * the bbuffer array can be nearly twice the size we need. */
1406 if ((data = (l_uint8 *)LEPT_CALLOC(bb->n + 1, sizeof(l_uint8))) != NULL) {
1407 memcpy(data, bb->array, bb->n);
1408 *pnbytes = bb->n;
1409 } else {
1410 L_ERROR("calloc fail for data\n", __func__);
1411 }
1412
1413 bbufferDestroy(&bb);
1414 return data;
1415}
1416
1417
1433l_uint8 *
1434l_binaryReadSelect(const char *filename,
1435 size_t start,
1436 size_t nbytes,
1437 size_t *pnread)
1438{
1439l_uint8 *data;
1440FILE *fp;
1441
1442 if (!pnread)
1443 return (l_uint8 *)ERROR_PTR("pnread not defined", __func__, NULL);
1444 *pnread = 0;
1445 if (!filename)
1446 return (l_uint8 *)ERROR_PTR("filename not defined", __func__, NULL);
1447
1448 if ((fp = fopenReadStream(filename)) == NULL)
1449 return (l_uint8 *)ERROR_PTR_1("file stream not opened",
1450 filename, __func__, NULL);
1451 data = l_binaryReadSelectStream(fp, start, nbytes, pnread);
1452 fclose(fp);
1453 return data;
1454}
1455
1456
1477l_uint8 *
1479 size_t start,
1480 size_t nbytes,
1481 size_t *pnread)
1482{
1483l_uint8 *data;
1484size_t bytesleft, bytestoread, nread, filebytes;
1485
1486 if (!pnread)
1487 return (l_uint8 *)ERROR_PTR("&nread not defined", __func__, NULL);
1488 *pnread = 0;
1489 if (!fp)
1490 return (l_uint8 *)ERROR_PTR("stream not defined", __func__, NULL);
1491
1492 /* Verify and adjust the parameters if necessary */
1493 fseek(fp, 0, SEEK_END); /* EOF */
1494 filebytes = ftell(fp);
1495 fseek(fp, 0, SEEK_SET);
1496 if (start > filebytes) {
1497 L_ERROR("start = %zu but filebytes = %zu\n", __func__,
1498 start, filebytes);
1499 return NULL;
1500 }
1501 if (filebytes == 0) /* start == 0; nothing to read; return null byte */
1502 return (l_uint8 *)LEPT_CALLOC(1, 1);
1503 bytesleft = filebytes - start; /* greater than 0 */
1504 if (nbytes == 0) nbytes = bytesleft;
1505 bytestoread = (bytesleft >= nbytes) ? nbytes : bytesleft;
1506
1507 /* Read the data */
1508 if ((data = (l_uint8 *)LEPT_CALLOC(1, bytestoread + 1)) == NULL)
1509 return (l_uint8 *)ERROR_PTR("calloc fail for data", __func__, NULL);
1510 fseek(fp, start, SEEK_SET);
1511 nread = fread(data, 1, bytestoread, fp);
1512 if (nbytes != nread)
1513 L_INFO("%zu bytes requested; %zu bytes read\n", __func__,
1514 nbytes, nread);
1515 *pnread = nread;
1516 fseek(fp, 0, SEEK_SET);
1517 return data;
1518}
1519
1520
1530l_ok
1531l_binaryWrite(const char *filename,
1532 const char *operation,
1533 const void *data,
1534 size_t nbytes)
1535{
1536char actualOperation[20];
1537FILE *fp;
1538
1539 if (!filename)
1540 return ERROR_INT("filename not defined", __func__, 1);
1541 if (!operation)
1542 return ERROR_INT("operation not defined", __func__, 1);
1543 if (!data)
1544 return ERROR_INT("data not defined", __func__, 1);
1545 if (nbytes <= 0)
1546 return ERROR_INT("nbytes must be > 0", __func__, 1);
1547
1548 if (strcmp(operation, "w") && strcmp(operation, "a"))
1549 return ERROR_INT("operation not one of {'w','a'}", __func__, 1);
1550
1551 /* The 'b' flag to fopen() is ignored for all POSIX
1552 * conforming systems. However, Windows needs the 'b' flag. */
1553 stringCopy(actualOperation, operation, 2);
1554 stringCat(actualOperation, 20, "b");
1555
1556 if ((fp = fopenWriteStream(filename, actualOperation)) == NULL)
1557 return ERROR_INT_1("stream not opened", filename, __func__, 1);
1558 fwrite(data, 1, nbytes, fp);
1559 fclose(fp);
1560 return 0;
1561}
1562
1563
1570size_t
1571nbytesInFile(const char *filename)
1572{
1573size_t nbytes;
1574FILE *fp;
1575
1576 if (!filename)
1577 return ERROR_INT("filename not defined", __func__, 0);
1578 if ((fp = fopenReadStream(filename)) == NULL)
1579 return ERROR_INT_1("stream not opened", filename, __func__, 0);
1580 nbytes = fnbytesInFile(fp);
1581 fclose(fp);
1582 return nbytes;
1583}
1584
1585
1592size_t
1594{
1595l_int64 pos, nbytes;
1596
1597 if (!fp)
1598 return ERROR_INT("stream not open", __func__, 0);
1599
1600 pos = ftell(fp); /* initial position */
1601 if (pos < 0)
1602 return ERROR_INT("seek position must be > 0", __func__, 0);
1603 fseek(fp, 0, SEEK_END); /* EOF */
1604 nbytes = ftell(fp);
1605 if (nbytes < 0)
1606 return ERROR_INT("nbytes is < 0", __func__, 0);
1607 fseek(fp, pos, SEEK_SET); /* back to initial position */
1608 return nbytes;
1609}
1610
1611
1612/*--------------------------------------------------------------------*
1613 * Copy and compare in memory *
1614 *--------------------------------------------------------------------*/
1630l_uint8 *
1631l_binaryCopy(const l_uint8 *datas,
1632 size_t size)
1633{
1634l_uint8 *datad;
1635
1636 if (!datas)
1637 return (l_uint8 *)ERROR_PTR("datas not defined", __func__, NULL);
1638
1639 if ((datad = (l_uint8 *)LEPT_CALLOC(size + 4, sizeof(l_uint8))) == NULL)
1640 return (l_uint8 *)ERROR_PTR("datad not made", __func__, NULL);
1641 memcpy(datad, datas, size);
1642 return datad;
1643}
1644
1645
1664l_ok
1665l_binaryCompare(const l_uint8 *data1,
1666 size_t size1,
1667 const l_uint8 *data2,
1668 size_t size2,
1669 l_int32 *psame)
1670{
1671l_int32 i;
1672
1673 if (!psame)
1674 return ERROR_INT("&same not defined", __func__, 1);
1675 *psame = FALSE;
1676 if (!data1 || !data2)
1677 return ERROR_INT("data1 and data2 not both defined", __func__, 1);
1678 if (size1 != size2) return 0;
1679 for (i = 0; i < size1; i++) {
1680 if (data1[i] != data2[i])
1681 return 0;
1682 }
1683 *psame = TRUE;
1684 return 0;
1685}
1686
1687
1688/*--------------------------------------------------------------------*
1689 * File copy operations *
1690 *--------------------------------------------------------------------*/
1698l_ok
1699fileCopy(const char *srcfile,
1700 const char *newfile)
1701{
1702l_int32 ret;
1703size_t nbytes;
1704l_uint8 *data;
1705
1706 if (!srcfile)
1707 return ERROR_INT("srcfile not defined", __func__, 1);
1708 if (!newfile)
1709 return ERROR_INT("newfile not defined", __func__, 1);
1710
1711 if ((data = l_binaryRead(srcfile, &nbytes)) == NULL)
1712 return ERROR_INT("data not returned", __func__, 1);
1713 ret = l_binaryWrite(newfile, "w", data, nbytes);
1714 LEPT_FREE(data);
1715 return ret;
1716}
1717
1718
1726l_ok
1727fileConcatenate(const char *srcfile,
1728 const char *destfile)
1729{
1730size_t nbytes;
1731l_uint8 *data;
1732
1733 if (!srcfile)
1734 return ERROR_INT("srcfile not defined", __func__, 1);
1735 if (!destfile)
1736 return ERROR_INT("destfile not defined", __func__, 1);
1737
1738 data = l_binaryRead(srcfile, &nbytes);
1739 l_binaryWrite(destfile, "a", data, nbytes);
1740 LEPT_FREE(data);
1741 return 0;
1742}
1743
1744
1752l_ok
1753fileAppendString(const char *filename,
1754 const char *str)
1755{
1756FILE *fp;
1757
1758 if (!filename)
1759 return ERROR_INT("filename not defined", __func__, 1);
1760 if (!str)
1761 return ERROR_INT("str not defined", __func__, 1);
1762
1763 if ((fp = fopenWriteStream(filename, "a")) == NULL)
1764 return ERROR_INT_1("stream not opened", filename, __func__, 1);
1765 fprintf(fp, "%s", str);
1766 fclose(fp);
1767 return 0;
1768}
1769
1770
1771/*--------------------------------------------------------------------*
1772 * File split operations *
1773 *--------------------------------------------------------------------*/
1800l_ok
1801fileSplitLinesUniform(const char *filename,
1802 l_int32 n,
1803 l_int32 save_empty,
1804 const char *rootpath,
1805 const char *ext)
1806{
1807l_int32 i, totlines, nlines, index;
1808size_t nbytes;
1809l_uint8 *data;
1810char *str;
1811char outname[512];
1812NUMA *na;
1813SARRAY *sa;
1814
1815 if (!filename)
1816 return ERROR_INT("filename not defined", __func__, 1);
1817 if (!rootpath)
1818 return ERROR_INT("rootpath not defined", __func__, 1);
1819 if (n <= 0)
1820 return ERROR_INT("n must be > 0", __func__, 1);
1821 if (save_empty != 0 && save_empty != 1)
1822 return ERROR_INT("save_empty not 0 or 1", __func__, 1);
1823
1824 /* Make sarray of lines; the newlines are stripped off */
1825 if ((data = l_binaryRead(filename, &nbytes)) == NULL)
1826 return ERROR_INT("data not read", __func__, 1);
1827 sa = sarrayCreateLinesFromString((const char *)data, save_empty);
1828 LEPT_FREE(data);
1829 if (!sa)
1830 return ERROR_INT("sa not made", __func__, 1);
1831 totlines = sarrayGetCount(sa);
1832 if (n > totlines) {
1833 sarrayDestroy(&sa);
1834 L_ERROR("num files = %d > num lines = %d\n", __func__, n, totlines);
1835 return 1;
1836 }
1837
1838 /* Write n sets of lines to n files, adding the newlines back */
1839 na = numaGetUniformBinSizes(totlines, n);
1840 index = 0;
1841 for (i = 0; i < n; i++) {
1842 if (ext == NULL)
1843 snprintf(outname, sizeof(outname), "%s_%d", rootpath, i);
1844 else
1845 snprintf(outname, sizeof(outname), "%s_%d%s", rootpath, i, ext);
1846 numaGetIValue(na, i, &nlines);
1847 str = sarrayToStringRange(sa, index, nlines, 1); /* add newlines */
1848 l_binaryWrite(outname, "w", str, strlen(str));
1849 LEPT_FREE(str);
1850 index += nlines;
1851 }
1852 numaDestroy(&na);
1853 sarrayDestroy(&sa);
1854 return 0;
1855}
1856
1857
1858/*--------------------------------------------------------------------*
1859 * Multi-platform functions for opening file streams *
1860 *--------------------------------------------------------------------*/
1875FILE *
1876fopenReadStream(const char *filename)
1877{
1878char *fname, *tail;
1879FILE *fp;
1880
1881 if (!filename)
1882 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
1883
1884 /* Try input filename */
1885 fname = genPathname(filename, NULL);
1886 fp = fopen(fname, "rb");
1887 LEPT_FREE(fname);
1888 if (fp) return fp;
1889
1890 /* Else, strip directory and try locally */
1891 splitPathAtDirectory(filename, NULL, &tail);
1892 if (!tail)
1893 return (FILE*)ERROR_PTR_1("tail not found", filename, __func__, NULL);
1894 fp = fopen(tail, "rb");
1895 if (!fp)
1896 L_ERROR("failed to open locally with tail %s for filename %s\n",
1897 __func__, tail, filename);
1898 LEPT_FREE(tail);
1899 return fp;
1900}
1901
1902
1918FILE *
1919fopenWriteStream(const char *filename,
1920 const char *modestring)
1921{
1922char *fname;
1923FILE *fp;
1924
1925 if (!filename)
1926 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
1927
1928 fname = genPathname(filename, NULL);
1929 fp = fopen(fname, modestring);
1930 if (!fp)
1931 fp = (FILE *)ERROR_PTR_1("stream not opened", fname, __func__, NULL);
1932 LEPT_FREE(fname);
1933 return fp;
1934}
1935
1936
1950FILE *
1951fopenReadFromMemory(const l_uint8 *data,
1952 size_t size)
1953{
1954FILE *fp;
1955
1956 if (!data)
1957 return (FILE *)ERROR_PTR("data not defined", __func__, NULL);
1958
1959#if HAVE_FMEMOPEN
1960 if ((fp = fmemopen((void *)data, size, "rb")) == NULL)
1961 return (FILE *)ERROR_PTR("stream not opened", __func__, NULL);
1962#else /* write to tmp file */
1963 L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
1964 #ifdef _WIN32
1965 if ((fp = fopenWriteWinTempfile()) == NULL)
1966 return (FILE *)ERROR_PTR("tmpfile stream not opened", __func__, NULL);
1967 #else
1968 if ((fp = tmpfile()) == NULL)
1969 return (FILE *)ERROR_PTR("tmpfile stream not opened", __func__, NULL);
1970 #endif /* _WIN32 */
1971 fwrite(data, 1, size, fp);
1972 rewind(fp);
1973#endif /* HAVE_FMEMOPEN */
1974
1975 return fp;
1976}
1977
1978
1979/*--------------------------------------------------------------------*
1980 * Opening a Windows tmpfile for writing *
1981 *--------------------------------------------------------------------*/
1994FILE *
1996{
1997#ifdef _WIN32
1998l_int32 handle;
1999FILE *fp;
2000char *filename;
2001
2002 if ((filename = l_makeTempFilename()) == NULL) {
2003 L_ERROR("l_makeTempFilename failed, %s\n", __func__, strerror(errno));
2004 return NULL;
2005 }
2006
2007 handle = _open(filename, _O_CREAT | _O_RDWR | _O_SHORT_LIVED |
2008 _O_TEMPORARY | _O_BINARY, _S_IREAD | _S_IWRITE);
2009 lept_free(filename);
2010 if (handle == -1) {
2011 L_ERROR("_open failed, %s\n", __func__, strerror(errno));
2012 return NULL;
2013 }
2014
2015 if ((fp = _fdopen(handle, "r+b")) == NULL) {
2016 L_ERROR("_fdopen failed, %s\n", __func__, strerror(errno));
2017 return NULL;
2018 }
2019
2020 return fp;
2021#else
2022 return NULL;
2023#endif /* _WIN32 */
2024}
2025
2026
2027/*--------------------------------------------------------------------*
2028 * Multi-platform functions that avoid C-runtime boundary *
2029 * crossing for applications with Windows DLLs *
2030 *--------------------------------------------------------------------*/
2031/*
2032 * Problems arise when pointers to streams and data are passed
2033 * between two Windows DLLs that have been generated with different
2034 * C runtimes. To avoid this, leptonica provides wrappers for
2035 * several C library calls.
2036 */
2050FILE *
2051lept_fopen(const char *filename,
2052 const char *mode)
2053{
2054 if (!filename)
2055 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
2056 if (!mode)
2057 return (FILE *)ERROR_PTR("mode not defined", __func__, NULL);
2058
2059 if (stringFindSubstr(mode, "r", NULL))
2060 return fopenReadStream(filename);
2061 else
2062 return fopenWriteStream(filename, mode);
2063}
2064
2065
2078l_ok
2080{
2081 if (!fp)
2082 return ERROR_INT("stream not defined", __func__, 1);
2083
2084 return fclose(fp);
2085}
2086
2087
2102void *
2103lept_calloc(size_t nmemb,
2104 size_t size)
2105{
2106 if (nmemb <= 0 || size <= 0)
2107 return NULL;
2108 return LEPT_CALLOC(nmemb, size);
2109}
2110
2111
2123void
2124lept_free(void *ptr)
2125{
2126 if (!ptr) return;
2127 LEPT_FREE(ptr);
2128}
2129
2130
2131/*--------------------------------------------------------------------*
2132 * Multi-platform file system operations *
2133 * [ These only write to /tmp or its subdirectories ] *
2134 *--------------------------------------------------------------------*/
2151l_int32
2152lept_mkdir(const char *subdir)
2153{
2154char *dir, *tmpdir;
2155l_int32 i, n;
2156l_int32 ret = 0;
2157SARRAY *sa;
2158#ifdef _WIN32
2159l_uint32 attributes;
2160#endif /* _WIN32 */
2161
2162 if (!LeptDebugOK) {
2163 L_INFO("making named temp subdirectory %s is disabled\n",
2164 __func__, subdir);
2165 return 0;
2166 }
2167
2168 if (!subdir)
2169 return ERROR_INT("subdir not defined", __func__, 1);
2170 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2171 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
2172
2173 sa = sarrayCreate(0);
2174 sarraySplitString(sa, subdir, "/");
2175 n = sarrayGetCount(sa);
2176 dir = genPathname("/tmp", NULL);
2177 /* Make sure the tmp directory exists */
2178#ifndef _WIN32
2179 ret = mkdir(dir, 0777);
2180#else
2181 attributes = GetFileAttributesA(dir);
2182 if (attributes == INVALID_FILE_ATTRIBUTES)
2183 ret = (CreateDirectoryA(dir, NULL) ? 0 : 1);
2184#endif
2185 /* Make all the subdirectories */
2186 for (i = 0; i < n; i++) {
2187 tmpdir = pathJoin(dir, sarrayGetString(sa, i, L_NOCOPY));
2188#ifndef _WIN32
2189 ret += mkdir(tmpdir, 0777);
2190#else
2191 if (CreateDirectoryA(tmpdir, NULL) == 0)
2192 ret += (GetLastError() != ERROR_ALREADY_EXISTS);
2193#endif
2194 LEPT_FREE(dir);
2195 dir = tmpdir;
2196 }
2197 LEPT_FREE(dir);
2198 sarrayDestroy(&sa);
2199 if (ret > 0)
2200 L_ERROR("failure to create %d directories\n", __func__, ret);
2201 return ret;
2202}
2203
2204
2226l_int32
2227lept_rmdir(const char *subdir)
2228{
2229char *dir, *fname, *fullname;
2230l_int32 exists, ret, i, nfiles;
2231SARRAY *sa;
2232#ifdef _WIN32
2233char *newpath;
2234#else
2235char *realdir;
2236#endif /* _WIN32 */
2237
2238 if (!subdir)
2239 return ERROR_INT("subdir not defined", __func__, 1);
2240 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2241 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
2242
2243 /* Find the temp subdirectory */
2244 dir = pathJoin("/tmp", subdir);
2245 if (!dir)
2246 return ERROR_INT("directory name not made", __func__, 1);
2247 lept_direxists(dir, &exists);
2248 if (!exists) { /* fail silently */
2249 LEPT_FREE(dir);
2250 return 0;
2251 }
2252
2253 /* List all the files in that directory */
2254 if ((sa = getFilenamesInDirectory(dir)) == NULL) {
2255 L_ERROR("directory %s does not exist!\n", __func__, dir);
2256 LEPT_FREE(dir);
2257 return 1;
2258 }
2259 nfiles = sarrayGetCount(sa);
2260
2261 for (i = 0; i < nfiles; i++) {
2262 fname = sarrayGetString(sa, i, L_NOCOPY);
2263 fullname = genPathname(dir, fname);
2264 remove(fullname);
2265 LEPT_FREE(fullname);
2266 }
2267
2268#ifndef _WIN32
2269 realdir = genPathname("/tmp", subdir);
2270 ret = rmdir(realdir);
2271 LEPT_FREE(realdir);
2272#else
2273 newpath = genPathname(dir, NULL);
2274 ret = (RemoveDirectoryA(newpath) ? 0 : 1);
2275 LEPT_FREE(newpath);
2276#endif /* !_WIN32 */
2277
2278 sarrayDestroy(&sa);
2279 LEPT_FREE(dir);
2280 return ret;
2281}
2282
2283
2299void
2300lept_direxists(const char *dir,
2301 l_int32 *pexists)
2302{
2303char *realdir;
2304
2305 if (!pexists) return;
2306 *pexists = 0;
2307 if (!dir) return;
2308 if ((realdir = genPathname(dir, NULL)) == NULL)
2309 return;
2310
2311#ifndef _WIN32
2312 {
2313 struct stat s;
2314 l_int32 err = stat(realdir, &s);
2315 if (err != -1 && S_ISDIR(s.st_mode))
2316 *pexists = 1;
2317 }
2318#else /* _WIN32 */
2319 {
2320 l_uint32 attributes;
2321 attributes = GetFileAttributesA(realdir);
2322 if (attributes != INVALID_FILE_ATTRIBUTES &&
2323 (attributes & FILE_ATTRIBUTE_DIRECTORY))
2324 *pexists = 1;
2325 }
2326#endif /* _WIN32 */
2327
2328 LEPT_FREE(realdir);
2329}
2330
2331
2356l_int32
2357lept_rm_match(const char *subdir,
2358 const char *substr)
2359{
2360char *path, *fname;
2361char tempdir[256];
2362l_int32 i, n, ret;
2363SARRAY *sa;
2364
2365 makeTempDirname(tempdir, sizeof(tempdir), subdir);
2366 if ((sa = getSortedPathnamesInDirectory(tempdir, substr, 0, 0)) == NULL)
2367 return ERROR_INT("sa not made", __func__, -1);
2368 n = sarrayGetCount(sa);
2369 if (n == 0) {
2370 L_WARNING("no matching files found\n", __func__);
2371 sarrayDestroy(&sa);
2372 return 0;
2373 }
2374
2375 ret = 0;
2376 for (i = 0; i < n; i++) {
2377 fname = sarrayGetString(sa, i, L_NOCOPY);
2378 path = genPathname(fname, NULL);
2379 if (lept_rmfile(path) != 0) {
2380 L_ERROR("failed to remove %s\n", __func__, path);
2381 ret++;
2382 }
2383 LEPT_FREE(path);
2384 }
2385 sarrayDestroy(&sa);
2386 return ret;
2387}
2388
2389
2403l_int32
2404lept_rm(const char *subdir,
2405 const char *tail)
2406{
2407char *path;
2408char newtemp[256];
2409l_int32 ret;
2410
2411 if (!tail || strlen(tail) == 0)
2412 return ERROR_INT("tail undefined or empty", __func__, 1);
2413
2414 if (makeTempDirname(newtemp, sizeof(newtemp), subdir))
2415 return ERROR_INT("temp dirname not made", __func__, 1);
2416 path = genPathname(newtemp, tail);
2417 ret = lept_rmfile(path);
2418 LEPT_FREE(path);
2419 return ret;
2420}
2421
2422
2444l_int32
2445lept_rmfile(const char *filepath)
2446{
2447l_int32 ret;
2448
2449 if (!filepath || strlen(filepath) == 0)
2450 return ERROR_INT("filepath undefined or empty", __func__, 1);
2451
2452#ifndef _WIN32
2453 ret = remove(filepath);
2454#else
2455 /* Set attributes to allow deletion of read-only files */
2456 SetFileAttributesA(filepath, FILE_ATTRIBUTE_NORMAL);
2457 ret = DeleteFileA(filepath) ? 0 : 1;
2458#endif /* !_WIN32 */
2459
2460 return ret;
2461}
2462
2463
2496l_int32
2497lept_mv(const char *srcfile,
2498 const char *newdir,
2499 const char *newtail,
2500 char **pnewpath)
2501{
2502char *srcpath, *newpath, *dir, *srctail;
2503char newtemp[256];
2504l_int32 ret;
2505
2506 if (!srcfile)
2507 return ERROR_INT("srcfile not defined", __func__, 1);
2508
2509 /* Require output pathname to be in /tmp/ or a subdirectory */
2510 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2511 return ERROR_INT("newdir not NULL or a subdir of /tmp", __func__, 1);
2512
2513 /* Get canonical src pathname */
2514 splitPathAtDirectory(srcfile, &dir, &srctail);
2515
2516#ifndef _WIN32
2517 srcpath = pathJoin(dir, srctail);
2518 LEPT_FREE(dir);
2519
2520 /* Generate output pathname */
2521 if (!newtail || newtail[0] == '\0')
2522 newpath = pathJoin(newtemp, srctail);
2523 else
2524 newpath = pathJoin(newtemp, newtail);
2525 LEPT_FREE(srctail);
2526
2527 /* Overwrite any existing file at 'newpath' */
2528 ret = fileCopy(srcpath, newpath);
2529 if (!ret) { /* and remove srcfile */
2530 char *realpath = genPathname(srcpath, NULL);
2531 remove(realpath);
2532 LEPT_FREE(realpath);
2533 }
2534#else
2535 srcpath = genPathname(dir, srctail);
2536 LEPT_FREE(dir);
2537
2538 /* Generate output pathname */
2539 if (!newtail || newtail[0] == '\0')
2540 newpath = genPathname(newtemp, srctail);
2541 else
2542 newpath = genPathname(newtemp, newtail);
2543 LEPT_FREE(srctail);
2544
2545 /* Overwrite any existing file at 'newpath' */
2546 ret = MoveFileExA(srcpath, newpath,
2547 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) ? 0 : 1;
2548#endif /* ! _WIN32 */
2549
2550 LEPT_FREE(srcpath);
2551 if (pnewpath)
2552 *pnewpath = newpath;
2553 else
2554 LEPT_FREE(newpath);
2555 return ret;
2556}
2557
2558
2592l_int32
2593lept_cp(const char *srcfile,
2594 const char *newdir,
2595 const char *newtail,
2596 char **pnewpath)
2597{
2598char *srcpath, *newpath, *dir, *srctail;
2599char newtemp[256];
2600l_int32 ret;
2601
2602 if (!srcfile)
2603 return ERROR_INT("srcfile not defined", __func__, 1);
2604
2605 /* Require output pathname to be in /tmp or a subdirectory */
2606 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2607 return ERROR_INT("newdir not NULL or a subdir of /tmp", __func__, 1);
2608
2609 /* Get canonical src pathname */
2610 splitPathAtDirectory(srcfile, &dir, &srctail);
2611
2612#ifndef _WIN32
2613 srcpath = pathJoin(dir, srctail);
2614 LEPT_FREE(dir);
2615
2616 /* Generate output pathname */
2617 if (!newtail || newtail[0] == '\0')
2618 newpath = pathJoin(newtemp, srctail);
2619 else
2620 newpath = pathJoin(newtemp, newtail);
2621 LEPT_FREE(srctail);
2622
2623 /* Overwrite any existing file at 'newpath' */
2624 ret = fileCopy(srcpath, newpath);
2625#else
2626 srcpath = genPathname(dir, srctail);
2627 LEPT_FREE(dir);
2628
2629 /* Generate output pathname */
2630 if (!newtail || newtail[0] == '\0')
2631 newpath = genPathname(newtemp, srctail);
2632 else
2633 newpath = genPathname(newtemp, newtail);
2634 LEPT_FREE(srctail);
2635
2636 /* Overwrite any existing file at 'newpath' */
2637 ret = CopyFileA(srcpath, newpath, FALSE) ? 0 : 1;
2638#endif /* !_WIN32 */
2639
2640 LEPT_FREE(srcpath);
2641 if (pnewpath)
2642 *pnewpath = newpath;
2643 else
2644 LEPT_FREE(newpath);
2645 return ret;
2646}
2647
2648
2649/*--------------------------------------------------------------------*
2650 * Special debug/test function for calling 'system' *
2651 *--------------------------------------------------------------------*/
2652#if defined(__APPLE__)
2653 #include "TargetConditionals.h"
2654#endif /* __APPLE__ */
2655
2671l_int32
2672callSystemDebug(const char *cmd)
2673{
2674l_int32 ret;
2675
2676 if (!cmd) {
2677 L_ERROR("cmd not defined\n", __func__);
2678 return 1;
2679 }
2680 if (LeptDebugOK == FALSE) {
2681 L_INFO("'system' calls are disabled\n", __func__);
2682 return 1;
2683 }
2684
2685#if defined(__APPLE__) /* iOS 11 does not support system() */
2686
2687 #if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) /* Mac OS X */
2688 ret = system(cmd);
2689 #elif TARGET_OS_IPHONE || defined(OS_IOS) /* iOS */
2690 L_ERROR("iOS 11 does not support system()\n", __func__);
2691 #endif /* TARGET_OS_OSX */
2692
2693#else /* ! __APPLE__ */
2694
2695 ret = system(cmd);
2696
2697#endif /* __APPLE__ */
2698
2699 return ret;
2700}
2701
2702
2703/*--------------------------------------------------------------------*
2704 * General file name operations *
2705 *--------------------------------------------------------------------*/
2743l_ok
2744splitPathAtDirectory(const char *pathname,
2745 char **pdir,
2746 char **ptail)
2747{
2748char *cpathname, *lastslash;
2749
2750 if (!pdir && !ptail)
2751 return ERROR_INT("null input for both strings", __func__, 1);
2752 if (pdir) *pdir = NULL;
2753 if (ptail) *ptail = NULL;
2754 if (!pathname)
2755 return ERROR_INT("pathname not defined", __func__, 1);
2756
2757 cpathname = stringNew(pathname);
2758 convertSepCharsInPath(cpathname, UNIX_PATH_SEPCHAR);
2759 lastslash = strrchr(cpathname, '/');
2760 if (lastslash) {
2761 if (ptail)
2762 *ptail = stringNew(lastslash + 1);
2763 if (pdir) {
2764 *(lastslash + 1) = '\0';
2765 *pdir = cpathname;
2766 } else {
2767 LEPT_FREE(cpathname);
2768 }
2769 } else { /* no directory */
2770 if (pdir)
2771 *pdir = stringNew("");
2772 if (ptail)
2773 *ptail = cpathname;
2774 else
2775 LEPT_FREE(cpathname);
2776 }
2777
2778 return 0;
2779}
2780
2781
2811l_ok
2812splitPathAtExtension(const char *pathname,
2813 char **pbasename,
2814 char **pextension)
2815{
2816char *tail, *dir, *lastdot;
2817char empty[4] = "";
2818
2819 if (!pbasename && !pextension)
2820 return ERROR_INT("null input for both strings", __func__, 1);
2821 if (pbasename) *pbasename = NULL;
2822 if (pextension) *pextension = NULL;
2823 if (!pathname)
2824 return ERROR_INT("pathname not defined", __func__, 1);
2825
2826 /* Split out the directory first */
2827 splitPathAtDirectory(pathname, &dir, &tail);
2828
2829 /* Then look for a "." in the tail part.
2830 * This way we ignore all "." in the directory. */
2831 if ((lastdot = strrchr(tail, '.'))) {
2832 if (pextension)
2833 *pextension = stringNew(lastdot);
2834 if (pbasename) {
2835 *lastdot = '\0';
2836 *pbasename = stringJoin(dir, tail);
2837 }
2838 } else {
2839 if (pextension)
2840 *pextension = stringNew(empty);
2841 if (pbasename)
2842 *pbasename = stringNew(pathname);
2843 }
2844 LEPT_FREE(dir);
2845 LEPT_FREE(tail);
2846 return 0;
2847}
2848
2849
2888char *
2889pathJoin(const char *dir,
2890 const char *fname)
2891{
2892const char *slash = "/";
2893char *str, *dest;
2894l_int32 i, n1, n2, emptydir;
2895size_t size;
2896SARRAY *sa1, *sa2;
2897L_BYTEA *ba;
2898
2899 if (!dir && !fname)
2900 return stringNew("");
2901 if (dir && strlen(dir) >= 2 && dir[0] == '.' && dir[1] == '.')
2902 return (char *)ERROR_PTR("dir starts with '..'", __func__, NULL);
2903 if (fname && strlen(fname) >= 2 && fname[0] == '.' && fname[1] == '.')
2904 return (char *)ERROR_PTR("fname starts with '..'", __func__, NULL);
2905
2906 sa1 = sarrayCreate(0);
2907 sa2 = sarrayCreate(0);
2908 ba = l_byteaCreate(4);
2909
2910 /* Process %dir */
2911 if (dir && strlen(dir) > 0) {
2912 if (dir[0] == '/')
2913 l_byteaAppendString(ba, slash);
2914 sarraySplitString(sa1, dir, "/"); /* removes all slashes */
2915 n1 = sarrayGetCount(sa1);
2916 for (i = 0; i < n1; i++) {
2917 str = sarrayGetString(sa1, i, L_NOCOPY);
2918 l_byteaAppendString(ba, str);
2919 l_byteaAppendString(ba, slash);
2920 }
2921 }
2922
2923 /* Special case to add leading slash: dir NULL or empty string */
2924 emptydir = dir && strlen(dir) == 0;
2925 if ((!dir || emptydir) && fname && strlen(fname) > 0 && fname[0] == '/')
2926 l_byteaAppendString(ba, slash);
2927
2928 /* Process %fname */
2929 if (fname && strlen(fname) > 0) {
2930 sarraySplitString(sa2, fname, "/");
2931 n2 = sarrayGetCount(sa2);
2932 for (i = 0; i < n2; i++) {
2933 str = sarrayGetString(sa2, i, L_NOCOPY);
2934 l_byteaAppendString(ba, str);
2935 l_byteaAppendString(ba, slash);
2936 }
2937 }
2938
2939 /* Remove trailing slash */
2940 dest = (char *)l_byteaCopyData(ba, &size);
2941 if (size > 1 && dest[size - 1] == '/')
2942 dest[size - 1] = '\0';
2943
2944 sarrayDestroy(&sa1);
2945 sarrayDestroy(&sa2);
2946 l_byteaDestroy(&ba);
2947 return dest;
2948}
2949
2950
2965char *
2966appendSubdirs(const char *basedir,
2967 const char *subdirs)
2968{
2969char *newdir;
2970size_t len1, len2, len3, len4;
2971
2972 if (!basedir || !subdirs)
2973 return (char *)ERROR_PTR("basedir and subdirs not both defined",
2974 __func__, NULL);
2975
2976 len1 = strlen(basedir);
2977 len2 = strlen(subdirs);
2978 len3 = len1 + len2 + 8;
2979 if ((newdir = (char *)LEPT_CALLOC(len3, 1)) == NULL)
2980 return (char *)ERROR_PTR("newdir not made", __func__, NULL);
2981 stringCat(newdir, len3, basedir);
2982 if (newdir[len1 - 1] != '/') /* add '/' if necessary */
2983 newdir[len1] = '/';
2984 if (subdirs[0] == '/') /* add subdirs, stripping leading '/' */
2985 stringCat(newdir, len3, subdirs + 1);
2986 else
2987 stringCat(newdir, len3, subdirs);
2988 len4 = strlen(newdir);
2989 if (newdir[len4 - 1] == '/') /* strip trailing '/' */
2990 newdir[len4 - 1] = '\0';
2991
2992 return newdir;
2993}
2994
2995
2996/*--------------------------------------------------------------------*
2997 * Special file name operations *
2998 *--------------------------------------------------------------------*/
3019l_ok
3021 l_int32 type)
3022{
3023l_int32 i;
3024size_t len;
3025
3026 if (!path)
3027 return ERROR_INT("path not defined", __func__, 1);
3028 if (type != UNIX_PATH_SEPCHAR && type != WIN_PATH_SEPCHAR)
3029 return ERROR_INT("invalid type", __func__, 1);
3030
3031 len = strlen(path);
3032 if (type == UNIX_PATH_SEPCHAR) {
3033#ifdef _WIN32 /* only convert on Windows */
3034 for (i = 0; i < len; i++) {
3035 if (path[i] == '\\')
3036 path[i] = '/';
3037 }
3038#endif /* _WIN32 */
3039 } else { /* WIN_PATH_SEPCHAR */
3040 for (i = 0; i < len; i++) {
3041 if (path[i] == '/')
3042 path[i] = '\\';
3043 }
3044 }
3045 return 0;
3046}
3047
3048
3085char *
3086genPathname(const char *dir,
3087 const char *fname)
3088{
3089#if defined(REWRITE_TMP)
3090l_int32 rewrite_tmp = TRUE;
3091#else
3092l_int32 rewrite_tmp = FALSE;
3093#endif /* REWRITE_TMP */
3094char *cdir, *pathout;
3095l_int32 dirlen, namelen;
3096size_t size;
3097
3098 if (!dir && !fname)
3099 return (char *)ERROR_PTR("no input", __func__, NULL);
3100
3101 /* Handle the case where we start from the current directory */
3102 if (!dir || dir[0] == '\0') {
3103 if ((cdir = getcwd(NULL, 0)) == NULL)
3104 return (char *)ERROR_PTR("no current dir found", __func__, NULL);
3105 } else {
3106 if ((cdir = stringNew(dir)) == NULL)
3107 return (char *)ERROR_PTR("stringNew failed", __func__, NULL);
3108 }
3109
3110 /* Convert to unix path separators, and remove the trailing
3111 * slash in the directory, except when dir == "/" */
3112 convertSepCharsInPath(cdir, UNIX_PATH_SEPCHAR);
3113 dirlen = strlen(cdir);
3114 if (cdir[dirlen - 1] == '/' && dirlen != 1) {
3115 cdir[dirlen - 1] = '\0';
3116 dirlen--;
3117 }
3118
3119 namelen = (fname) ? strlen(fname) : 0;
3120 size = dirlen + namelen + 256;
3121 if ((pathout = (char *)LEPT_CALLOC(size, sizeof(char))) == NULL) {
3122 LEPT_FREE(cdir);
3123 return (char *)ERROR_PTR("pathout not made", __func__, NULL);
3124 }
3125
3126 /* First handle %dir (which may be a full pathname).
3127 * There is no path rewriting on unix, and on win32, we do not
3128 * rewrite unless the specified directory is /tmp or
3129 * a subdirectory of /tmp */
3130 if (!rewrite_tmp || dirlen < 4 ||
3131 (dirlen == 4 && strncmp(cdir, "/tmp", 4) != 0) || /* not in "/tmp" */
3132 (dirlen > 4 && strncmp(cdir, "/tmp/", 5) != 0)) { /* not in "/tmp/" */
3133 stringCopy(pathout, cdir, dirlen);
3134 } else { /* Rewrite with "/tmp" specified for the directory. */
3135#if defined(__APPLE__)
3136 size_t n = confstr(_CS_DARWIN_USER_TEMP_DIR, pathout, size);
3137 if (n == 0 || n > size) {
3138 /* Fall back to using /tmp */
3139 stringCopy(pathout, cdir, dirlen);
3140 } else {
3141 /* Add the rest of cdir */
3142 if (dirlen > 4)
3143 stringCat(pathout, size, cdir + 4);
3144 }
3145#elif defined(_WIN32)
3146 l_int32 tmpdirlen;
3147 char tmpdir[MAX_PATH];
3148 GetTempPathA(sizeof(tmpdir), tmpdir); /* get the Windows temp dir */
3149 tmpdirlen = strlen(tmpdir);
3150 if (tmpdirlen > 0 && tmpdir[tmpdirlen - 1] == '\\') {
3151 tmpdir[tmpdirlen - 1] = '\0'; /* trim the trailing '\' */
3152 }
3153 tmpdirlen = strlen(tmpdir);
3154 stringCopy(pathout, tmpdir, tmpdirlen);
3155
3156 /* Add the rest of cdir */
3157 if (dirlen > 4)
3158 stringCat(pathout, size, cdir + 4);
3159#endif /* _WIN32 */
3160 }
3161
3162 /* Now handle %fname */
3163 if (fname && strlen(fname) > 0) {
3164 dirlen = strlen(pathout);
3165 pathout[dirlen] = '/';
3166 stringCat(pathout, size, fname);
3167 }
3168
3169 LEPT_FREE(cdir);
3170 return pathout;
3171}
3172
3173
3201l_ok
3202makeTempDirname(char *result,
3203 size_t nbytes,
3204 const char *subdir)
3205{
3206char *dir, *path;
3207l_int32 ret = 0;
3208size_t pathlen;
3209
3210 if (!result)
3211 return ERROR_INT("result not defined", __func__, 1);
3212 if (subdir && ((subdir[0] == '.') || (subdir[0] == '/')))
3213 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
3214
3215 memset(result, 0, nbytes);
3216
3217 dir = pathJoin("/tmp", subdir);
3218
3219#if defined(REWRITE_TMP)
3220 path = genPathname(dir, NULL);
3221#else
3222 path = stringNew(dir);
3223#endif /* ~ _WIN32 */
3224 pathlen = strlen(path);
3225 if (pathlen < nbytes - 1) {
3226 stringCopy(result, path, nbytes);
3227 } else {
3228 L_ERROR("result array too small for path\n", __func__);
3229 ret = 1;
3230 }
3231
3232 LEPT_FREE(dir);
3233 LEPT_FREE(path);
3234 return ret;
3235}
3236
3237
3251l_ok
3253 size_t nbytes,
3254 l_int32 flag)
3255{
3256char lastchar;
3257size_t len;
3258
3259 if (!path)
3260 return ERROR_INT("path not defined", __func__, 1);
3261 if (flag != L_ADD_TRAIL_SLASH && flag != L_REMOVE_TRAIL_SLASH)
3262 return ERROR_INT("invalid flag", __func__, 1);
3263
3264 len = strlen(path);
3265 lastchar = path[len - 1];
3266 if (flag == L_ADD_TRAIL_SLASH && lastchar != '/' && len < nbytes - 2) {
3267 path[len] = '/';
3268 path[len + 1] = '\0';
3269 } else if (flag == L_REMOVE_TRAIL_SLASH && lastchar == '/') {
3270 path[len - 1] = '\0';
3271 }
3272 return 0;
3273}
3274
3275
3299char *
3301{
3302char dirname[240];
3303
3304 if (makeTempDirname(dirname, sizeof(dirname), NULL) == 1)
3305 return (char *)ERROR_PTR("failed to make dirname", __func__, NULL);
3306
3307#ifndef _WIN32
3308{
3309 char *pattern;
3310 l_int32 fd;
3311 pattern = stringConcatNew(dirname, "/lept.XXXXXX", NULL);
3312 fd = mkstemp(pattern);
3313 if (fd == -1) {
3314 LEPT_FREE(pattern);
3315 return (char *)ERROR_PTR("mkstemp failed", __func__, NULL);
3316 }
3317 close(fd);
3318 return pattern;
3319}
3320#else
3321{
3322 char fname[MAX_PATH];
3323 FILE *fp;
3324 if (GetTempFileNameA(dirname, "lp.", 0, fname) == 0)
3325 return (char *)ERROR_PTR("GetTempFileName failed", __func__, NULL);
3326 if ((fp = fopen(fname, "wb")) == NULL)
3327 return (char *)ERROR_PTR("file cannot be written to", __func__, NULL);
3328 fclose(fp);
3329 return stringNew(fname);
3330}
3331#endif /* ~ _WIN32 */
3332}
3333
3334
3353l_int32
3355 l_int32 numpre,
3356 l_int32 numpost)
3357{
3358char *tail, *basename;
3359l_int32 len, nret, num;
3360
3361 if (!fname)
3362 return ERROR_INT("fname not defined", __func__, -1);
3363
3364 splitPathAtDirectory(fname, NULL, &tail);
3365 splitPathAtExtension(tail, &basename, NULL);
3366 LEPT_FREE(tail);
3367
3368 len = strlen(basename);
3369 if (numpre + numpost > len - 1) {
3370 LEPT_FREE(basename);
3371 return ERROR_INT("numpre + numpost too big", __func__, -1);
3372 }
3373
3374 basename[len - numpost] = '\0';
3375 nret = sscanf(basename + numpre, "%d", &num);
3376 LEPT_FREE(basename);
3377
3378 if (nret == 1)
3379 return num;
3380 else
3381 return -1; /* not found */
3382}
@ L_NOCOPY
Definition pix.h:503
@ L_ADD_TRAIL_SLASH
Definition pix.h:1082
@ L_REMOVE_TRAIL_SLASH
Definition pix.h:1083
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:378
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition utils2.c:1571
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition utils2.c:2227
char * stringCopySegment(const char *src, l_int32 start, l_int32 nbytes)
stringCopySegment()
Definition utils2.c:305
void lept_direxists(const char *dir, l_int32 *pexists)
lept_direxists()
Definition utils2.c:2300
l_int32 lept_rm(const char *subdir, const char *tail)
lept_rm()
Definition utils2.c:2404
l_ok lept_fclose(FILE *fp)
lept_fclose()
Definition utils2.c:2079
char * stringReverse(const char *src)
stringReverse()
Definition utils2.c:589
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition utils2.c:2445
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition utils2.c:1995
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition utils2.c:2889
l_uint8 * l_binaryCopy(const l_uint8 *datas, size_t size)
l_binaryCopy()
Definition utils2.c:1631
l_uint8 * l_binaryReadSelectStream(FILE *fp, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelectStream()
Definition utils2.c:1478
l_ok fileAppendString(const char *filename, const char *str)
fileAppendString()
Definition utils2.c:1753
l_int32 lept_rm_match(const char *subdir, const char *substr)
lept_rm_match()
Definition utils2.c:2357
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition utils2.c:343
char * strtokSafe(char *cstr, const char *seps, char **psaveptr)
strtokSafe()
Definition utils2.c:639
l_ok fileConcatenate(const char *srcfile, const char *destfile)
fileConcatenate()
Definition utils2.c:1727
l_ok stringJoinIP(char **psrc1, const char *src2)
stringJoinIP()
Definition utils2.c:567
char * stringRemoveChars(const char *src, const char *remchars)
stringRemoveChars()
Definition utils2.c:806
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition utils2.c:1919
void lept_free(void *ptr)
lept_free()
Definition utils2.c:2124
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition utils2.c:3300
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition utils2.c:3252
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition utils2.c:2812
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition utils2.c:3086
l_int32 lept_cp(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_cp()
Definition utils2.c:2593
l_int32 lept_mv(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_mv()
Definition utils2.c:2497
l_ok stringCheckForChars(const char *src, const char *chars, l_int32 *pfound)
stringCheckForChars()
Definition utils2.c:773
FILE * lept_fopen(const char *filename, const char *mode)
lept_fopen()
Definition utils2.c:2051
l_int32 callSystemDebug(const char *cmd)
callSystemDebug()
Definition utils2.c:2672
char * stringReplaceEachSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *pcount)
stringReplaceEachSubstr()
Definition utils2.c:860
char * stringConcatNew(const char *first,...)
stringConcatNew()
Definition utils2.c:467
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:1665
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition utils2.c:1593
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition utils2.c:2744
l_uint8 * l_binaryReadSelect(const char *filename, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelect()
Definition utils2.c:1434
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition utils2.c:1320
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition utils2.c:1951
l_int32 stringFindSubstr(const char *src, const char *sub, l_int32 *ploc)
stringFindSubstr()
Definition utils2.c:1003
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition utils2.c:514
l_ok convertSepCharsInPath(char *path, l_int32 type)
convertSepCharsInPath()
Definition utils2.c:3020
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition utils2.c:421
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition utils2.c:1876
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition utils2.c:1369
char * stringReplaceSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *ploc, l_int32 *pfound)
stringReplaceSubstr()
Definition utils2.c:915
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition utils2.c:1272
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition utils2.c:2152
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition utils2.c:1145
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:1056
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition utils2.c:1531
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition utils2.c:3202
l_ok stringSplitOnToken(char *cstr, const char *seps, char **phead, char **ptail)
stringSplitOnToken()
Definition utils2.c:731
void * lept_calloc(size_t nmemb, size_t size)
lept_calloc()
Definition utils2.c:2103
L_DNA * stringFindEachSubstr(const char *src, const char *sub)
stringFindEachSubstr()
Definition utils2.c:974
char * stringNew(const char *src)
stringNew()
Definition utils2.c:227
l_ok stringCopy(char *dest, const char *src, l_int32 n)
stringCopy()
Definition utils2.c:265
l_ok fileSplitLinesUniform(const char *filename, l_int32 n, l_int32 save_empty, const char *rootpath, const char *ext)
fileSplitLinesUniform()
Definition utils2.c:1801
l_int32 extractNumberFromFilename(const char *fname, l_int32 numpre, l_int32 numpost)
extractNumberFromFilename()
Definition utils2.c:3354
char * appendSubdirs(const char *basedir, const char *subdirs)
appendSubdirs()
Definition utils2.c:2966
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:1205
l_ok fileCopy(const char *srcfile, const char *newfile)
fileCopy()
Definition utils2.c:1699