Leptonica 1.84.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
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 %d 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 fp = (FILE *)ERROR_PTR_1("file not found", tail, __func__, NULL);
1897 LEPT_FREE(tail);
1898 return fp;
1899}
1900
1901
1917FILE *
1918fopenWriteStream(const char *filename,
1919 const char *modestring)
1920{
1921char *fname;
1922FILE *fp;
1923
1924 if (!filename)
1925 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
1926
1927 fname = genPathname(filename, NULL);
1928 fp = fopen(fname, modestring);
1929 if (!fp)
1930 fp = (FILE *)ERROR_PTR_1("stream not opened", fname, __func__, NULL);
1931 LEPT_FREE(fname);
1932 return fp;
1933}
1934
1935
1949FILE *
1950fopenReadFromMemory(const l_uint8 *data,
1951 size_t size)
1952{
1953FILE *fp;
1954
1955 if (!data)
1956 return (FILE *)ERROR_PTR("data not defined", __func__, NULL);
1957
1958#if HAVE_FMEMOPEN
1959 if ((fp = fmemopen((void *)data, size, "rb")) == NULL)
1960 return (FILE *)ERROR_PTR("stream not opened", __func__, NULL);
1961#else /* write to tmp file */
1962 L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
1963 #ifdef _WIN32
1964 if ((fp = fopenWriteWinTempfile()) == NULL)
1965 return (FILE *)ERROR_PTR("tmpfile stream not opened", __func__, NULL);
1966 #else
1967 if ((fp = tmpfile()) == NULL)
1968 return (FILE *)ERROR_PTR("tmpfile stream not opened", __func__, NULL);
1969 #endif /* _WIN32 */
1970 fwrite(data, 1, size, fp);
1971 rewind(fp);
1972#endif /* HAVE_FMEMOPEN */
1973
1974 return fp;
1975}
1976
1977
1978/*--------------------------------------------------------------------*
1979 * Opening a Windows tmpfile for writing *
1980 *--------------------------------------------------------------------*/
1993FILE *
1995{
1996#ifdef _WIN32
1997l_int32 handle;
1998FILE *fp;
1999char *filename;
2000
2001 if ((filename = l_makeTempFilename()) == NULL) {
2002 L_ERROR("l_makeTempFilename failed, %s\n", __func__, strerror(errno));
2003 return NULL;
2004 }
2005
2006 handle = _open(filename, _O_CREAT | _O_RDWR | _O_SHORT_LIVED |
2007 _O_TEMPORARY | _O_BINARY, _S_IREAD | _S_IWRITE);
2008 lept_free(filename);
2009 if (handle == -1) {
2010 L_ERROR("_open failed, %s\n", __func__, strerror(errno));
2011 return NULL;
2012 }
2013
2014 if ((fp = _fdopen(handle, "r+b")) == NULL) {
2015 L_ERROR("_fdopen failed, %s\n", __func__, strerror(errno));
2016 return NULL;
2017 }
2018
2019 return fp;
2020#else
2021 return NULL;
2022#endif /* _WIN32 */
2023}
2024
2025
2026/*--------------------------------------------------------------------*
2027 * Multi-platform functions that avoid C-runtime boundary *
2028 * crossing for applications with Windows DLLs *
2029 *--------------------------------------------------------------------*/
2030/*
2031 * Problems arise when pointers to streams and data are passed
2032 * between two Windows DLLs that have been generated with different
2033 * C runtimes. To avoid this, leptonica provides wrappers for
2034 * several C library calls.
2035 */
2049FILE *
2050lept_fopen(const char *filename,
2051 const char *mode)
2052{
2053 if (!filename)
2054 return (FILE *)ERROR_PTR("filename not defined", __func__, NULL);
2055 if (!mode)
2056 return (FILE *)ERROR_PTR("mode not defined", __func__, NULL);
2057
2058 if (stringFindSubstr(mode, "r", NULL))
2059 return fopenReadStream(filename);
2060 else
2061 return fopenWriteStream(filename, mode);
2062}
2063
2064
2077l_ok
2079{
2080 if (!fp)
2081 return ERROR_INT("stream not defined", __func__, 1);
2082
2083 return fclose(fp);
2084}
2085
2086
2101void *
2102lept_calloc(size_t nmemb,
2103 size_t size)
2104{
2105 if (nmemb <= 0 || size <= 0)
2106 return NULL;
2107 return LEPT_CALLOC(nmemb, size);
2108}
2109
2110
2122void
2123lept_free(void *ptr)
2124{
2125 if (!ptr) return;
2126 LEPT_FREE(ptr);
2127}
2128
2129
2130/*--------------------------------------------------------------------*
2131 * Multi-platform file system operations *
2132 * [ These only write to /tmp or its subdirectories ] *
2133 *--------------------------------------------------------------------*/
2150l_int32
2151lept_mkdir(const char *subdir)
2152{
2153char *dir, *tmpdir;
2154l_int32 i, n;
2155l_int32 ret = 0;
2156SARRAY *sa;
2157#ifdef _WIN32
2158l_uint32 attributes;
2159#endif /* _WIN32 */
2160
2161 if (!LeptDebugOK) {
2162 L_INFO("making named temp subdirectory %s is disabled\n",
2163 __func__, subdir);
2164 return 0;
2165 }
2166
2167 if (!subdir)
2168 return ERROR_INT("subdir not defined", __func__, 1);
2169 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2170 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
2171
2172 sa = sarrayCreate(0);
2173 sarraySplitString(sa, subdir, "/");
2174 n = sarrayGetCount(sa);
2175 dir = genPathname("/tmp", NULL);
2176 /* Make sure the tmp directory exists */
2177#ifndef _WIN32
2178 ret = mkdir(dir, 0777);
2179#else
2180 attributes = GetFileAttributesA(dir);
2181 if (attributes == INVALID_FILE_ATTRIBUTES)
2182 ret = (CreateDirectoryA(dir, NULL) ? 0 : 1);
2183#endif
2184 /* Make all the subdirectories */
2185 for (i = 0; i < n; i++) {
2186 tmpdir = pathJoin(dir, sarrayGetString(sa, i, L_NOCOPY));
2187#ifndef _WIN32
2188 ret += mkdir(tmpdir, 0777);
2189#else
2190 if (CreateDirectoryA(tmpdir, NULL) == 0)
2191 ret += (GetLastError() != ERROR_ALREADY_EXISTS);
2192#endif
2193 LEPT_FREE(dir);
2194 dir = tmpdir;
2195 }
2196 LEPT_FREE(dir);
2197 sarrayDestroy(&sa);
2198 if (ret > 0)
2199 L_ERROR("failure to create %d directories\n", __func__, ret);
2200 return ret;
2201}
2202
2203
2225l_int32
2226lept_rmdir(const char *subdir)
2227{
2228char *dir, *fname, *fullname;
2229l_int32 exists, ret, i, nfiles;
2230SARRAY *sa;
2231#ifdef _WIN32
2232char *newpath;
2233#else
2234char *realdir;
2235#endif /* _WIN32 */
2236
2237 if (!subdir)
2238 return ERROR_INT("subdir not defined", __func__, 1);
2239 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2240 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
2241
2242 /* Find the temp subdirectory */
2243 dir = pathJoin("/tmp", subdir);
2244 if (!dir)
2245 return ERROR_INT("directory name not made", __func__, 1);
2246 lept_direxists(dir, &exists);
2247 if (!exists) { /* fail silently */
2248 LEPT_FREE(dir);
2249 return 0;
2250 }
2251
2252 /* List all the files in that directory */
2253 if ((sa = getFilenamesInDirectory(dir)) == NULL) {
2254 L_ERROR("directory %s does not exist!\n", __func__, dir);
2255 LEPT_FREE(dir);
2256 return 1;
2257 }
2258 nfiles = sarrayGetCount(sa);
2259
2260 for (i = 0; i < nfiles; i++) {
2261 fname = sarrayGetString(sa, i, L_NOCOPY);
2262 fullname = genPathname(dir, fname);
2263 remove(fullname);
2264 LEPT_FREE(fullname);
2265 }
2266
2267#ifndef _WIN32
2268 realdir = genPathname("/tmp", subdir);
2269 ret = rmdir(realdir);
2270 LEPT_FREE(realdir);
2271#else
2272 newpath = genPathname(dir, NULL);
2273 ret = (RemoveDirectoryA(newpath) ? 0 : 1);
2274 LEPT_FREE(newpath);
2275#endif /* !_WIN32 */
2276
2277 sarrayDestroy(&sa);
2278 LEPT_FREE(dir);
2279 return ret;
2280}
2281
2282
2298void
2299lept_direxists(const char *dir,
2300 l_int32 *pexists)
2301{
2302char *realdir;
2303
2304 if (!pexists) return;
2305 *pexists = 0;
2306 if (!dir) return;
2307 if ((realdir = genPathname(dir, NULL)) == NULL)
2308 return;
2309
2310#ifndef _WIN32
2311 {
2312 struct stat s;
2313 l_int32 err = stat(realdir, &s);
2314 if (err != -1 && S_ISDIR(s.st_mode))
2315 *pexists = 1;
2316 }
2317#else /* _WIN32 */
2318 {
2319 l_uint32 attributes;
2320 attributes = GetFileAttributesA(realdir);
2321 if (attributes != INVALID_FILE_ATTRIBUTES &&
2322 (attributes & FILE_ATTRIBUTE_DIRECTORY))
2323 *pexists = 1;
2324 }
2325#endif /* _WIN32 */
2326
2327 LEPT_FREE(realdir);
2328}
2329
2330
2355l_int32
2356lept_rm_match(const char *subdir,
2357 const char *substr)
2358{
2359char *path, *fname;
2360char tempdir[256];
2361l_int32 i, n, ret;
2362SARRAY *sa;
2363
2364 makeTempDirname(tempdir, sizeof(tempdir), subdir);
2365 if ((sa = getSortedPathnamesInDirectory(tempdir, substr, 0, 0)) == NULL)
2366 return ERROR_INT("sa not made", __func__, -1);
2367 n = sarrayGetCount(sa);
2368 if (n == 0) {
2369 L_WARNING("no matching files found\n", __func__);
2370 sarrayDestroy(&sa);
2371 return 0;
2372 }
2373
2374 ret = 0;
2375 for (i = 0; i < n; i++) {
2376 fname = sarrayGetString(sa, i, L_NOCOPY);
2377 path = genPathname(fname, NULL);
2378 if (lept_rmfile(path) != 0) {
2379 L_ERROR("failed to remove %s\n", __func__, path);
2380 ret++;
2381 }
2382 LEPT_FREE(path);
2383 }
2384 sarrayDestroy(&sa);
2385 return ret;
2386}
2387
2388
2402l_int32
2403lept_rm(const char *subdir,
2404 const char *tail)
2405{
2406char *path;
2407char newtemp[256];
2408l_int32 ret;
2409
2410 if (!tail || strlen(tail) == 0)
2411 return ERROR_INT("tail undefined or empty", __func__, 1);
2412
2413 if (makeTempDirname(newtemp, sizeof(newtemp), subdir))
2414 return ERROR_INT("temp dirname not made", __func__, 1);
2415 path = genPathname(newtemp, tail);
2416 ret = lept_rmfile(path);
2417 LEPT_FREE(path);
2418 return ret;
2419}
2420
2421
2443l_int32
2444lept_rmfile(const char *filepath)
2445{
2446l_int32 ret;
2447
2448 if (!filepath || strlen(filepath) == 0)
2449 return ERROR_INT("filepath undefined or empty", __func__, 1);
2450
2451#ifndef _WIN32
2452 ret = remove(filepath);
2453#else
2454 /* Set attributes to allow deletion of read-only files */
2455 SetFileAttributesA(filepath, FILE_ATTRIBUTE_NORMAL);
2456 ret = DeleteFileA(filepath) ? 0 : 1;
2457#endif /* !_WIN32 */
2458
2459 return ret;
2460}
2461
2462
2495l_int32
2496lept_mv(const char *srcfile,
2497 const char *newdir,
2498 const char *newtail,
2499 char **pnewpath)
2500{
2501char *srcpath, *newpath, *dir, *srctail;
2502char newtemp[256];
2503l_int32 ret;
2504
2505 if (!srcfile)
2506 return ERROR_INT("srcfile not defined", __func__, 1);
2507
2508 /* Require output pathname to be in /tmp/ or a subdirectory */
2509 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2510 return ERROR_INT("newdir not NULL or a subdir of /tmp", __func__, 1);
2511
2512 /* Get canonical src pathname */
2513 splitPathAtDirectory(srcfile, &dir, &srctail);
2514
2515#ifndef _WIN32
2516 srcpath = pathJoin(dir, srctail);
2517 LEPT_FREE(dir);
2518
2519 /* Generate output pathname */
2520 if (!newtail || newtail[0] == '\0')
2521 newpath = pathJoin(newtemp, srctail);
2522 else
2523 newpath = pathJoin(newtemp, newtail);
2524 LEPT_FREE(srctail);
2525
2526 /* Overwrite any existing file at 'newpath' */
2527 ret = fileCopy(srcpath, newpath);
2528 if (!ret) { /* and remove srcfile */
2529 char *realpath = genPathname(srcpath, NULL);
2530 remove(realpath);
2531 LEPT_FREE(realpath);
2532 }
2533#else
2534 srcpath = genPathname(dir, srctail);
2535 LEPT_FREE(dir);
2536
2537 /* Generate output pathname */
2538 if (!newtail || newtail[0] == '\0')
2539 newpath = genPathname(newtemp, srctail);
2540 else
2541 newpath = genPathname(newtemp, newtail);
2542 LEPT_FREE(srctail);
2543
2544 /* Overwrite any existing file at 'newpath' */
2545 ret = MoveFileExA(srcpath, newpath,
2546 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) ? 0 : 1;
2547#endif /* ! _WIN32 */
2548
2549 LEPT_FREE(srcpath);
2550 if (pnewpath)
2551 *pnewpath = newpath;
2552 else
2553 LEPT_FREE(newpath);
2554 return ret;
2555}
2556
2557
2591l_int32
2592lept_cp(const char *srcfile,
2593 const char *newdir,
2594 const char *newtail,
2595 char **pnewpath)
2596{
2597char *srcpath, *newpath, *dir, *srctail;
2598char newtemp[256];
2599l_int32 ret;
2600
2601 if (!srcfile)
2602 return ERROR_INT("srcfile not defined", __func__, 1);
2603
2604 /* Require output pathname to be in /tmp or a subdirectory */
2605 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2606 return ERROR_INT("newdir not NULL or a subdir of /tmp", __func__, 1);
2607
2608 /* Get canonical src pathname */
2609 splitPathAtDirectory(srcfile, &dir, &srctail);
2610
2611#ifndef _WIN32
2612 srcpath = pathJoin(dir, srctail);
2613 LEPT_FREE(dir);
2614
2615 /* Generate output pathname */
2616 if (!newtail || newtail[0] == '\0')
2617 newpath = pathJoin(newtemp, srctail);
2618 else
2619 newpath = pathJoin(newtemp, newtail);
2620 LEPT_FREE(srctail);
2621
2622 /* Overwrite any existing file at 'newpath' */
2623 ret = fileCopy(srcpath, newpath);
2624#else
2625 srcpath = genPathname(dir, srctail);
2626 LEPT_FREE(dir);
2627
2628 /* Generate output pathname */
2629 if (!newtail || newtail[0] == '\0')
2630 newpath = genPathname(newtemp, srctail);
2631 else
2632 newpath = genPathname(newtemp, newtail);
2633 LEPT_FREE(srctail);
2634
2635 /* Overwrite any existing file at 'newpath' */
2636 ret = CopyFileA(srcpath, newpath, FALSE) ? 0 : 1;
2637#endif /* !_WIN32 */
2638
2639 LEPT_FREE(srcpath);
2640 if (pnewpath)
2641 *pnewpath = newpath;
2642 else
2643 LEPT_FREE(newpath);
2644 return ret;
2645}
2646
2647
2648/*--------------------------------------------------------------------*
2649 * Special debug/test function for calling 'system' *
2650 *--------------------------------------------------------------------*/
2651#if defined(__APPLE__)
2652 #include "TargetConditionals.h"
2653#endif /* __APPLE__ */
2654
2670void
2671callSystemDebug(const char *cmd)
2672{
2673l_int32 ret;
2674
2675 if (!cmd) {
2676 L_ERROR("cmd not defined\n", __func__);
2677 return;
2678 }
2679 if (LeptDebugOK == FALSE) {
2680 L_INFO("'system' calls are disabled\n", __func__);
2681 return;
2682 }
2683
2684#if defined(__APPLE__) /* iOS 11 does not support system() */
2685
2686 #if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) /* Mac OS X */
2687 ret = system(cmd);
2688 #elif TARGET_OS_IPHONE || defined(OS_IOS) /* iOS */
2689 L_ERROR("iOS 11 does not support system()\n", __func__);
2690 #endif /* TARGET_OS_OSX */
2691
2692#else /* ! __APPLE__ */
2693
2694 ret = system(cmd);
2695
2696#endif /* __APPLE__ */
2697}
2698
2699
2700/*--------------------------------------------------------------------*
2701 * General file name operations *
2702 *--------------------------------------------------------------------*/
2740l_ok
2741splitPathAtDirectory(const char *pathname,
2742 char **pdir,
2743 char **ptail)
2744{
2745char *cpathname, *lastslash;
2746
2747 if (!pdir && !ptail)
2748 return ERROR_INT("null input for both strings", __func__, 1);
2749 if (pdir) *pdir = NULL;
2750 if (ptail) *ptail = NULL;
2751 if (!pathname)
2752 return ERROR_INT("pathname not defined", __func__, 1);
2753
2754 cpathname = stringNew(pathname);
2755 convertSepCharsInPath(cpathname, UNIX_PATH_SEPCHAR);
2756 lastslash = strrchr(cpathname, '/');
2757 if (lastslash) {
2758 if (ptail)
2759 *ptail = stringNew(lastslash + 1);
2760 if (pdir) {
2761 *(lastslash + 1) = '\0';
2762 *pdir = cpathname;
2763 } else {
2764 LEPT_FREE(cpathname);
2765 }
2766 } else { /* no directory */
2767 if (pdir)
2768 *pdir = stringNew("");
2769 if (ptail)
2770 *ptail = cpathname;
2771 else
2772 LEPT_FREE(cpathname);
2773 }
2774
2775 return 0;
2776}
2777
2778
2808l_ok
2809splitPathAtExtension(const char *pathname,
2810 char **pbasename,
2811 char **pextension)
2812{
2813char *tail, *dir, *lastdot;
2814char empty[4] = "";
2815
2816 if (!pbasename && !pextension)
2817 return ERROR_INT("null input for both strings", __func__, 1);
2818 if (pbasename) *pbasename = NULL;
2819 if (pextension) *pextension = NULL;
2820 if (!pathname)
2821 return ERROR_INT("pathname not defined", __func__, 1);
2822
2823 /* Split out the directory first */
2824 splitPathAtDirectory(pathname, &dir, &tail);
2825
2826 /* Then look for a "." in the tail part.
2827 * This way we ignore all "." in the directory. */
2828 if ((lastdot = strrchr(tail, '.'))) {
2829 if (pextension)
2830 *pextension = stringNew(lastdot);
2831 if (pbasename) {
2832 *lastdot = '\0';
2833 *pbasename = stringJoin(dir, tail);
2834 }
2835 } else {
2836 if (pextension)
2837 *pextension = stringNew(empty);
2838 if (pbasename)
2839 *pbasename = stringNew(pathname);
2840 }
2841 LEPT_FREE(dir);
2842 LEPT_FREE(tail);
2843 return 0;
2844}
2845
2846
2885char *
2886pathJoin(const char *dir,
2887 const char *fname)
2888{
2889const char *slash = "/";
2890char *str, *dest;
2891l_int32 i, n1, n2, emptydir;
2892size_t size;
2893SARRAY *sa1, *sa2;
2894L_BYTEA *ba;
2895
2896 if (!dir && !fname)
2897 return stringNew("");
2898 if (dir && strlen(dir) >= 2 && dir[0] == '.' && dir[1] == '.')
2899 return (char *)ERROR_PTR("dir starts with '..'", __func__, NULL);
2900 if (fname && strlen(fname) >= 2 && fname[0] == '.' && fname[1] == '.')
2901 return (char *)ERROR_PTR("fname starts with '..'", __func__, NULL);
2902
2903 sa1 = sarrayCreate(0);
2904 sa2 = sarrayCreate(0);
2905 ba = l_byteaCreate(4);
2906
2907 /* Process %dir */
2908 if (dir && strlen(dir) > 0) {
2909 if (dir[0] == '/')
2910 l_byteaAppendString(ba, slash);
2911 sarraySplitString(sa1, dir, "/"); /* removes all slashes */
2912 n1 = sarrayGetCount(sa1);
2913 for (i = 0; i < n1; i++) {
2914 str = sarrayGetString(sa1, i, L_NOCOPY);
2915 l_byteaAppendString(ba, str);
2916 l_byteaAppendString(ba, slash);
2917 }
2918 }
2919
2920 /* Special case to add leading slash: dir NULL or empty string */
2921 emptydir = dir && strlen(dir) == 0;
2922 if ((!dir || emptydir) && fname && strlen(fname) > 0 && fname[0] == '/')
2923 l_byteaAppendString(ba, slash);
2924
2925 /* Process %fname */
2926 if (fname && strlen(fname) > 0) {
2927 sarraySplitString(sa2, fname, "/");
2928 n2 = sarrayGetCount(sa2);
2929 for (i = 0; i < n2; i++) {
2930 str = sarrayGetString(sa2, i, L_NOCOPY);
2931 l_byteaAppendString(ba, str);
2932 l_byteaAppendString(ba, slash);
2933 }
2934 }
2935
2936 /* Remove trailing slash */
2937 dest = (char *)l_byteaCopyData(ba, &size);
2938 if (size > 1 && dest[size - 1] == '/')
2939 dest[size - 1] = '\0';
2940
2941 sarrayDestroy(&sa1);
2942 sarrayDestroy(&sa2);
2943 l_byteaDestroy(&ba);
2944 return dest;
2945}
2946
2947
2962char *
2963appendSubdirs(const char *basedir,
2964 const char *subdirs)
2965{
2966char *newdir;
2967size_t len1, len2, len3, len4;
2968
2969 if (!basedir || !subdirs)
2970 return (char *)ERROR_PTR("basedir and subdirs not both defined",
2971 __func__, NULL);
2972
2973 len1 = strlen(basedir);
2974 len2 = strlen(subdirs);
2975 len3 = len1 + len2 + 8;
2976 if ((newdir = (char *)LEPT_CALLOC(len3, 1)) == NULL)
2977 return (char *)ERROR_PTR("newdir not made", __func__, NULL);
2978 stringCat(newdir, len3, basedir);
2979 if (newdir[len1 - 1] != '/') /* add '/' if necessary */
2980 newdir[len1] = '/';
2981 if (subdirs[0] == '/') /* add subdirs, stripping leading '/' */
2982 stringCat(newdir, len3, subdirs + 1);
2983 else
2984 stringCat(newdir, len3, subdirs);
2985 len4 = strlen(newdir);
2986 if (newdir[len4 - 1] == '/') /* strip trailing '/' */
2987 newdir[len4 - 1] = '\0';
2988
2989 return newdir;
2990}
2991
2992
2993/*--------------------------------------------------------------------*
2994 * Special file name operations *
2995 *--------------------------------------------------------------------*/
3016l_ok
3018 l_int32 type)
3019{
3020l_int32 i;
3021size_t len;
3022
3023 if (!path)
3024 return ERROR_INT("path not defined", __func__, 1);
3025 if (type != UNIX_PATH_SEPCHAR && type != WIN_PATH_SEPCHAR)
3026 return ERROR_INT("invalid type", __func__, 1);
3027
3028 len = strlen(path);
3029 if (type == UNIX_PATH_SEPCHAR) {
3030#ifdef _WIN32 /* only convert on Windows */
3031 for (i = 0; i < len; i++) {
3032 if (path[i] == '\\')
3033 path[i] = '/';
3034 }
3035#endif /* _WIN32 */
3036 } else { /* WIN_PATH_SEPCHAR */
3037 for (i = 0; i < len; i++) {
3038 if (path[i] == '/')
3039 path[i] = '\\';
3040 }
3041 }
3042 return 0;
3043}
3044
3045
3082char *
3083genPathname(const char *dir,
3084 const char *fname)
3085{
3086#if defined(REWRITE_TMP)
3087l_int32 rewrite_tmp = TRUE;
3088#else
3089l_int32 rewrite_tmp = FALSE;
3090#endif /* _WIN32 */
3091char *cdir, *pathout;
3092l_int32 dirlen, namelen;
3093size_t size;
3094
3095 if (!dir && !fname)
3096 return (char *)ERROR_PTR("no input", __func__, NULL);
3097
3098 /* Handle the case where we start from the current directory */
3099 if (!dir || dir[0] == '\0') {
3100 if ((cdir = getcwd(NULL, 0)) == NULL)
3101 return (char *)ERROR_PTR("no current dir found", __func__, NULL);
3102 } else {
3103 if ((cdir = stringNew(dir)) == NULL)
3104 return (char *)ERROR_PTR("stringNew failed", __func__, NULL);
3105 }
3106
3107 /* Convert to unix path separators, and remove the trailing
3108 * slash in the directory, except when dir == "/" */
3109 convertSepCharsInPath(cdir, UNIX_PATH_SEPCHAR);
3110 dirlen = strlen(cdir);
3111 if (cdir[dirlen - 1] == '/' && dirlen != 1) {
3112 cdir[dirlen - 1] = '\0';
3113 dirlen--;
3114 }
3115
3116 namelen = (fname) ? strlen(fname) : 0;
3117 size = dirlen + namelen + 256;
3118 if ((pathout = (char *)LEPT_CALLOC(size, sizeof(char))) == NULL) {
3119 LEPT_FREE(cdir);
3120 return (char *)ERROR_PTR("pathout not made", __func__, NULL);
3121 }
3122
3123 /* First handle %dir (which may be a full pathname).
3124 * There is no path rewriting on unix, and on win32, we do not
3125 * rewrite unless the specified directory is /tmp or
3126 * a subdirectory of /tmp */
3127 if (!rewrite_tmp || dirlen < 4 ||
3128 (dirlen == 4 && strncmp(cdir, "/tmp", 4) != 0) || /* not in "/tmp" */
3129 (dirlen > 4 && strncmp(cdir, "/tmp/", 5) != 0)) { /* not in "/tmp/" */
3130 stringCopy(pathout, cdir, dirlen);
3131 } else { /* Rewrite with "/tmp" specified for the directory. */
3132#if defined(__APPLE__)
3133 size_t n = confstr(_CS_DARWIN_USER_TEMP_DIR, pathout, size);
3134 if (n == 0 || n > size) {
3135 /* Fall back to using /tmp */
3136 stringCopy(pathout, cdir, dirlen);
3137 } else {
3138 /* Add the rest of cdir */
3139 if (dirlen > 4)
3140 stringCat(pathout, size, cdir + 4);
3141 }
3142#elif defined(_WIN32)
3143 l_int32 tmpdirlen;
3144 char tmpdir[MAX_PATH];
3145 GetTempPathA(sizeof(tmpdir), tmpdir); /* get the Windows temp dir */
3146 tmpdirlen = strlen(tmpdir);
3147 if (tmpdirlen > 0 && tmpdir[tmpdirlen - 1] == '\\') {
3148 tmpdir[tmpdirlen - 1] = '\0'; /* trim the trailing '\' */
3149 }
3150 tmpdirlen = strlen(tmpdir);
3151 stringCopy(pathout, tmpdir, tmpdirlen);
3152
3153 /* Add the rest of cdir */
3154 if (dirlen > 4)
3155 stringCat(pathout, size, cdir + 4);
3156#endif /* _WIN32 */
3157 }
3158
3159 /* Now handle %fname */
3160 if (fname && strlen(fname) > 0) {
3161 dirlen = strlen(pathout);
3162 pathout[dirlen] = '/';
3163 stringCat(pathout, size, fname);
3164 }
3165
3166 LEPT_FREE(cdir);
3167 return pathout;
3168}
3169
3170
3198l_ok
3199makeTempDirname(char *result,
3200 size_t nbytes,
3201 const char *subdir)
3202{
3203char *dir, *path;
3204l_int32 ret = 0;
3205size_t pathlen;
3206
3207 if (!result)
3208 return ERROR_INT("result not defined", __func__, 1);
3209 if (subdir && ((subdir[0] == '.') || (subdir[0] == '/')))
3210 return ERROR_INT("subdir not an actual subdirectory", __func__, 1);
3211
3212 memset(result, 0, nbytes);
3213
3214 dir = pathJoin("/tmp", subdir);
3215
3216#if defined(REWRITE_TMP)
3217 path = genPathname(dir, NULL);
3218#else
3219 path = stringNew(dir);
3220#endif /* ~ _WIN32 */
3221 pathlen = strlen(path);
3222 if (pathlen < nbytes - 1) {
3223 stringCopy(result, path, nbytes);
3224 } else {
3225 L_ERROR("result array too small for path\n", __func__);
3226 ret = 1;
3227 }
3228
3229 LEPT_FREE(dir);
3230 LEPT_FREE(path);
3231 return ret;
3232}
3233
3234
3248l_ok
3250 size_t nbytes,
3251 l_int32 flag)
3252{
3253char lastchar;
3254size_t len;
3255
3256 if (!path)
3257 return ERROR_INT("path not defined", __func__, 1);
3258 if (flag != L_ADD_TRAIL_SLASH && flag != L_REMOVE_TRAIL_SLASH)
3259 return ERROR_INT("invalid flag", __func__, 1);
3260
3261 len = strlen(path);
3262 lastchar = path[len - 1];
3263 if (flag == L_ADD_TRAIL_SLASH && lastchar != '/' && len < nbytes - 2) {
3264 path[len] = '/';
3265 path[len + 1] = '\0';
3266 } else if (flag == L_REMOVE_TRAIL_SLASH && lastchar == '/') {
3267 path[len - 1] = '\0';
3268 }
3269 return 0;
3270}
3271
3272
3296char *
3298{
3299char dirname[240];
3300
3301 if (makeTempDirname(dirname, sizeof(dirname), NULL) == 1)
3302 return (char *)ERROR_PTR("failed to make dirname", __func__, NULL);
3303
3304#ifndef _WIN32
3305{
3306 char *pattern;
3307 l_int32 fd;
3308 pattern = stringConcatNew(dirname, "/lept.XXXXXX", NULL);
3309 fd = mkstemp(pattern);
3310 if (fd == -1) {
3311 LEPT_FREE(pattern);
3312 return (char *)ERROR_PTR("mkstemp failed", __func__, NULL);
3313 }
3314 close(fd);
3315 return pattern;
3316}
3317#else
3318{
3319 char fname[MAX_PATH];
3320 FILE *fp;
3321 if (GetTempFileNameA(dirname, "lp.", 0, fname) == 0)
3322 return (char *)ERROR_PTR("GetTempFileName failed", __func__, NULL);
3323 if ((fp = fopen(fname, "wb")) == NULL)
3324 return (char *)ERROR_PTR("file cannot be written to", __func__, NULL);
3325 fclose(fp);
3326 return stringNew(fname);
3327}
3328#endif /* ~ _WIN32 */
3329}
3330
3331
3350l_int32
3352 l_int32 numpre,
3353 l_int32 numpost)
3354{
3355char *tail, *basename;
3356l_int32 len, nret, num;
3357
3358 if (!fname)
3359 return ERROR_INT("fname not defined", __func__, -1);
3360
3361 splitPathAtDirectory(fname, NULL, &tail);
3362 splitPathAtExtension(tail, &basename, NULL);
3363 LEPT_FREE(tail);
3364
3365 len = strlen(basename);
3366 if (numpre + numpost > len - 1) {
3367 LEPT_FREE(basename);
3368 return ERROR_INT("numpre + numpost too big", __func__, -1);
3369 }
3370
3371 basename[len - numpost] = '\0';
3372 nret = sscanf(basename + numpre, "%d", &num);
3373 LEPT_FREE(basename);
3374
3375 if (nret == 1)
3376 return num;
3377 else
3378 return -1; /* not found */
3379}
@ 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:2226
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:2299
l_int32 lept_rm(const char *subdir, const char *tail)
lept_rm()
Definition utils2.c:2403
l_ok lept_fclose(FILE *fp)
lept_fclose()
Definition utils2.c:2078
char * stringReverse(const char *src)
stringReverse()
Definition utils2.c:589
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition utils2.c:2444
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition utils2.c:1994
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition utils2.c:2886
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:2356
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:1918
void lept_free(void *ptr)
lept_free()
Definition utils2.c:2123
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition utils2.c:3297
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition utils2.c:3249
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition utils2.c:2809
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition utils2.c:3083
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition utils2.c:2671
l_int32 lept_cp(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_cp()
Definition utils2.c:2592
l_int32 lept_mv(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_mv()
Definition utils2.c:2496
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:2050
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:2741
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:1950
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:3017
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:2151
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:3199
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:2102
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:3351
char * appendSubdirs(const char *basedir, const char *subdirs)
appendSubdirs()
Definition utils2.c:2963
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