Leptonica 1.82.0
Image processing and image analysis suite
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
213/*--------------------------------------------------------------------*
214 * Safe string operations *
215 *--------------------------------------------------------------------*/
222char *
223stringNew(const char *src)
224{
225l_int32 len;
226char *dest;
227
228 PROCNAME("stringNew");
229
230 if (!src) {
231 L_WARNING("src not defined\n", procName);
232 return NULL;
233 }
234
235 len = strlen(src);
236 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
237 return (char *)ERROR_PTR("dest not made", procName, NULL);
238
239 stringCopy(dest, src, len);
240 return dest;
241}
242
243
262l_ok
263stringCopy(char *dest,
264 const char *src,
265 l_int32 n)
266{
267l_int32 i;
268
269 PROCNAME("stringCopy");
270
271 if (!dest)
272 return ERROR_INT("dest not defined", procName, 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 PROCNAME("stringCopySegment");
313
314 if (!src)
315 return (char *)ERROR_PTR("src not defined", procName, NULL);
316 len = strlen(src);
317 if (start < 0 || start > len - 1)
318 return (char *)ERROR_PTR("invalid start", procName, NULL);
319 if (nbytes <= 0) /* copy to the end */
320 nbytes = len - start;
321 if (start + nbytes > len) /* truncate to the end */
322 nbytes = len - start;
323 if ((dest = (char *)LEPT_CALLOC(nbytes + 1, sizeof(char))) == NULL)
324 return (char *)ERROR_PTR("dest not made", procName, NULL);
325 stringCopy(dest, src + start, nbytes);
326 return dest;
327}
328
329
344l_ok
345stringReplace(char **pdest,
346 const char *src)
347{
348 PROCNAME("stringReplace");
349
350 if (!pdest)
351 return ERROR_INT("pdest not defined", procName, 1);
352
353 if (*pdest)
354 LEPT_FREE(*pdest);
355
356 if (src)
357 *pdest = stringNew(src);
358 else
359 *pdest = NULL;
360 return 0;
361}
362
363
380l_int32
381stringLength(const char *src,
382 size_t size)
383{
384l_int32 i;
385
386 PROCNAME("stringLength");
387
388 if (!src)
389 return ERROR_INT("src not defined", procName, 0);
390 if (size < 1)
391 return 0;
392
393 for (i = 0; i < size; i++) {
394 if (src[i] == '\0')
395 return i;
396 }
397 return size; /* didn't find a NUL byte */
398}
399
400
422l_int32
423stringCat(char *dest,
424 size_t size,
425 const char *src)
426{
427l_int32 i, n;
428l_int32 lendest, lensrc;
429
430 PROCNAME("stringCat");
431
432 if (!dest)
433 return ERROR_INT("dest not defined", procName, -1);
434 if (size < 1)
435 return ERROR_INT("size < 1; too small", procName, -1);
436 if (!src)
437 return 0;
438
439 lendest = stringLength(dest, size);
440 if (lendest == size)
441 return ERROR_INT("no terminating nul byte", procName, -1);
442 lensrc = stringLength(src, size);
443 if (lensrc == 0)
444 return 0;
445 n = (lendest + lensrc > size - 1 ? 0 : lensrc);
446 if (n < 1)
447 return ERROR_INT("dest too small for append", procName, -1);
448
449 for (i = 0; i < n; i++)
450 dest[lendest + i] = src[i];
451 dest[lendest + n] = '\0';
452 return n;
453}
454
455
470char *
471stringConcatNew(const char *first, ...)
472{
473size_t len;
474char *result, *ptr;
475const char *arg;
476va_list args;
477
478 if (!first) return NULL;
479
480 /* Find the length of the output string */
481 va_start(args, first);
482 len = strlen(first);
483 while ((arg = va_arg(args, const char *)) != NULL)
484 len += strlen(arg);
485 va_end(args);
486 result = (char *)LEPT_CALLOC(len + 1, sizeof(char));
487
488 /* Concatenate the args */
489 va_start(args, first);
490 ptr = result;
491 arg = first;
492 while (*arg)
493 *ptr++ = *arg++;
494 while ((arg = va_arg(args, const char *)) != NULL) {
495 while (*arg)
496 *ptr++ = *arg++;
497 }
498 va_end(args);
499 return result;
500}
501
502
517char *
518stringJoin(const char *src1,
519 const char *src2)
520{
521char *dest;
522l_int32 srclen1, srclen2, destlen;
523
524 PROCNAME("stringJoin");
525
526 srclen1 = (src1) ? strlen(src1) : 0;
527 srclen2 = (src2) ? strlen(src2) : 0;
528 destlen = srclen1 + srclen2 + 3;
529
530 if ((dest = (char *)LEPT_CALLOC(destlen, sizeof(char))) == NULL)
531 return (char *)ERROR_PTR("calloc fail for dest", procName, NULL);
532
533 if (src1)
534 stringCat(dest, destlen, src1);
535 if (src2)
536 stringCat(dest, destlen, src2);
537 return dest;
538}
539
540
572l_ok
573stringJoinIP(char **psrc1,
574 const char *src2)
575{
576char *tmpstr;
577
578 PROCNAME("stringJoinIP");
579
580 if (!psrc1)
581 return ERROR_INT("&src1 not defined", procName, 1);
582
583 tmpstr = stringJoin(*psrc1, src2);
584 LEPT_FREE(*psrc1);
585 *psrc1 = tmpstr;
586 return 0;
587}
588
589
596char *
597stringReverse(const char *src)
598{
599char *dest;
600l_int32 i, len;
601
602 PROCNAME("stringReverse");
603
604 if (!src)
605 return (char *)ERROR_PTR("src not defined", procName, NULL);
606 len = strlen(src);
607 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
608 return (char *)ERROR_PTR("calloc fail for dest", procName, NULL);
609 for (i = 0; i < len; i++)
610 dest[i] = src[len - 1 - i];
611
612 return dest;
613}
614
615
648char *
649strtokSafe(char *cstr,
650 const char *seps,
651 char **psaveptr)
652{
653char nextc;
654char *start, *substr;
655l_int32 istart, i, j, nchars;
656
657 PROCNAME("strtokSafe");
658
659 if (!seps)
660 return (char *)ERROR_PTR("seps not defined", procName, NULL);
661 if (!psaveptr)
662 return (char *)ERROR_PTR("&saveptr not defined", procName, NULL);
663
664 if (!cstr) {
665 start = *psaveptr;
666 } else {
667 start = cstr;
668 *psaveptr = NULL;
669 }
670 if (!start) /* nothing to do */
671 return NULL;
672
673 /* First time, scan for the first non-sep character */
674 istart = 0;
675 if (cstr) {
676 for (istart = 0;; istart++) {
677 if ((nextc = start[istart]) == '\0') {
678 *psaveptr = NULL; /* in case caller doesn't check ret value */
679 return NULL;
680 }
681 if (!strchr(seps, nextc))
682 break;
683 }
684 }
685
686 /* Scan through, looking for a sep character; if none is
687 * found, 'i' will be at the end of the string. */
688 for (i = istart;; i++) {
689 if ((nextc = start[i]) == '\0')
690 break;
691 if (strchr(seps, nextc))
692 break;
693 }
694
695 /* Save the substring */
696 nchars = i - istart;
697 substr = (char *)LEPT_CALLOC(nchars + 1, sizeof(char));
698 stringCopy(substr, start + istart, nchars);
699
700 /* Look for the next non-sep character.
701 * If this is the last substring, return a null saveptr. */
702 for (j = i;; j++) {
703 if ((nextc = start[j]) == '\0') {
704 *psaveptr = NULL; /* no more non-sep characters */
705 break;
706 }
707 if (!strchr(seps, nextc)) {
708 *psaveptr = start + j; /* start here on next call */
709 break;
710 }
711 }
712
713 return substr;
714}
715
716
742l_ok
744 const char *seps,
745 char **phead,
746 char **ptail)
747{
748char *saveptr;
749
750 PROCNAME("stringSplitOnToken");
751
752 if (!phead)
753 return ERROR_INT("&head not defined", procName, 1);
754 if (!ptail)
755 return ERROR_INT("&tail not defined", procName, 1);
756 *phead = *ptail = NULL;
757 if (!cstr)
758 return ERROR_INT("cstr not defined", procName, 1);
759 if (!seps)
760 return ERROR_INT("seps not defined", procName, 1);
761
762 *phead = strtokSafe(cstr, seps, &saveptr);
763 if (saveptr)
764 *ptail = stringNew(saveptr);
765 return 0;
766}
767
768
769/*--------------------------------------------------------------------*
770 * Find and replace procs *
771 *--------------------------------------------------------------------*/
786l_ok
787stringCheckForChars(const char *src,
788 const char *chars,
789 l_int32 *pfound)
790{
791char ch;
792l_int32 i, n;
793
794 PROCNAME("stringCheckForChars");
795
796 if (!pfound)
797 return ERROR_INT("&found not defined", procName, 1);
798 *pfound = FALSE;
799 if (!src || !chars)
800 return ERROR_INT("src and chars not both defined", procName, 1);
801
802 n = strlen(src);
803 for (i = 0; i < n; i++) {
804 ch = src[i];
805 if (strchr(chars, ch)) {
806 *pfound = TRUE;
807 break;
808 }
809 }
810 return 0;
811}
812
813
821char *
822stringRemoveChars(const char *src,
823 const char *remchars)
824{
825char ch;
826char *dest;
827l_int32 nsrc, i, k;
828
829 PROCNAME("stringRemoveChars");
830
831 if (!src)
832 return (char *)ERROR_PTR("src not defined", procName, NULL);
833 if (!remchars)
834 return stringNew(src);
835
836 if ((dest = (char *)LEPT_CALLOC(strlen(src) + 1, sizeof(char))) == NULL)
837 return (char *)ERROR_PTR("dest not made", procName, NULL);
838 nsrc = strlen(src);
839 for (i = 0, k = 0; i < nsrc; i++) {
840 ch = src[i];
841 if (!strchr(remchars, ch))
842 dest[k++] = ch;
843 }
844
845 return dest;
846}
847
848
877char *
879 const char *sub1,
880 const char *sub2,
881 l_int32 *pcount)
882{
883size_t datalen;
884
885 PROCNAME("stringReplaceEachSubstr");
886
887 if (pcount) *pcount = 0;
888 if (!src || !sub1 || !sub2)
889 return (char *)ERROR_PTR("src, sub1, sub2 not all defined",
890 procName, NULL);
891
892 if (strlen(sub2) > 0) {
893 return (char *)arrayReplaceEachSequence(
894 (const l_uint8 *)src, strlen(src),
895 (const l_uint8 *)sub1, strlen(sub1),
896 (const l_uint8 *)sub2, strlen(sub2),
897 &datalen, pcount);
898 } else { /* empty replacement string; removal only */
899 return (char *)arrayReplaceEachSequence(
900 (const l_uint8 *)src, strlen(src),
901 (const l_uint8 *)sub1, strlen(sub1),
902 NULL, 0, &datalen, pcount);
903 }
904}
905
906
934char *
935stringReplaceSubstr(const char *src,
936 const char *sub1,
937 const char *sub2,
938 l_int32 *ploc,
939 l_int32 *pfound)
940{
941const char *ptr;
942char *dest;
943l_int32 nsrc, nsub1, nsub2, len, npre, loc;
944
945 PROCNAME("stringReplaceSubstr");
946
947 if (pfound) *pfound = 0;
948 if (!src || !sub1 || !sub2)
949 return (char *)ERROR_PTR("src, sub1, sub2 not all defined",
950 procName, NULL);
951
952 if (ploc)
953 loc = *ploc;
954 else
955 loc = 0;
956 if (!strcmp(sub1, sub2))
957 return stringNew(src);
958 if ((ptr = strstr(src + loc, sub1)) == NULL)
959 return stringNew(src);
960 if (pfound) *pfound = 1;
961
962 nsrc = strlen(src);
963 nsub1 = strlen(sub1);
964 nsub2 = strlen(sub2);
965 len = nsrc + nsub2 - nsub1;
966 if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
967 return (char *)ERROR_PTR("dest not made", procName, NULL);
968 npre = ptr - src;
969 memcpy(dest, src, npre);
970 strcpy(dest + npre, sub2);
971 strcpy(dest + npre + nsub2, ptr + nsub1);
972 if (ploc) *ploc = npre + nsub2;
973 return dest;
974}
975
976
995L_DNA *
996stringFindEachSubstr(const char *src,
997 const char *sub)
998{
999 PROCNAME("stringFindEachSubstr");
1000
1001 if (!src || !sub)
1002 return (L_DNA *)ERROR_PTR("src, sub not both defined", procName, NULL);
1003
1004 return arrayFindEachSequence((const l_uint8 *)src, strlen(src),
1005 (const l_uint8 *)sub, strlen(sub));
1006}
1007
1008
1026l_int32
1027stringFindSubstr(const char *src,
1028 const char *sub,
1029 l_int32 *ploc)
1030{
1031const char *ptr;
1032
1033 PROCNAME("stringFindSubstr");
1034
1035 if (ploc) *ploc = -1;
1036 if (!src || !sub)
1037 return ERROR_INT("src and sub not both defined", procName, 0);
1038 if (strlen(sub) == 0)
1039 return ERROR_INT("substring length 0", procName, 0);
1040 if (strlen(src) == 0)
1041 return 0;
1042
1043 if ((ptr = strstr(src, sub)) == NULL) /* not found */
1044 return 0;
1045
1046 if (ploc)
1047 *ploc = ptr - src;
1048 return 1;
1049}
1050
1051
1081l_uint8 *
1082arrayReplaceEachSequence(const l_uint8 *datas,
1083 size_t dataslen,
1084 const l_uint8 *seq,
1085 size_t seqlen,
1086 const l_uint8 *newseq,
1087 size_t newseqlen,
1088 size_t *pdatadlen,
1089 l_int32 *pcount)
1090{
1091l_uint8 *datad;
1092size_t newsize;
1093l_int32 n, i, j, di, si, index, incr;
1094L_DNA *da;
1095
1096 PROCNAME("arrayReplaceEachSequence");
1097
1098 if (pcount) *pcount = 0;
1099 if (!datas || !seq)
1100 return (l_uint8 *)ERROR_PTR("datas & seq not both defined",
1101 procName, NULL);
1102 if (!pdatadlen)
1103 return (l_uint8 *)ERROR_PTR("&datadlen not defined", procName, NULL);
1104 *pdatadlen = 0;
1105
1106 /* Identify the locations of the sequence. If there are none,
1107 * return a copy of %datas. */
1108 if ((da = arrayFindEachSequence(datas, dataslen, seq, seqlen)) == NULL) {
1109 *pdatadlen = dataslen;
1110 return l_binaryCopy(datas, dataslen);
1111 }
1112
1113 /* Allocate the output data; insure null termination */
1114 n = l_dnaGetCount(da);
1115 if (pcount) *pcount = n;
1116 if (!newseq) newseqlen = 0;
1117 newsize = dataslen + n * (newseqlen - seqlen) + 4;
1118 if ((datad = (l_uint8 *)LEPT_CALLOC(newsize, sizeof(l_uint8))) == NULL) {
1119 l_dnaDestroy(&da);
1120 return (l_uint8 *)ERROR_PTR("datad not made", procName, NULL);
1121 }
1122
1123 /* Replace each sequence instance with a new sequence */
1124 l_dnaGetIValue(da, 0, &si);
1125 for (i = 0, di = 0, index = 0; i < dataslen; i++) {
1126 if (i == si) {
1127 index++;
1128 if (index < n) {
1129 l_dnaGetIValue(da, index, &si);
1130 incr = L_MIN(seqlen, si - i); /* amount to remove from datas */
1131 } else {
1132 incr = seqlen;
1133 }
1134 i += incr - 1; /* jump over the matched sequence in datas */
1135 if (newseq) { /* add new sequence to datad */
1136 for (j = 0; j < newseqlen; j++)
1137 datad[di++] = newseq[j];
1138 }
1139 } else {
1140 datad[di++] = datas[i];
1141 }
1142 }
1143
1144 *pdatadlen = di;
1145 l_dnaDestroy(&da);
1146 return datad;
1147}
1148
1149
1172L_DNA *
1173arrayFindEachSequence(const l_uint8 *data,
1174 size_t datalen,
1175 const l_uint8 *sequence,
1176 size_t seqlen)
1177{
1178l_int32 start, offset, realoffset, found;
1179L_DNA *da;
1180
1181 PROCNAME("arrayFindEachSequence");
1182
1183 if (!data || !sequence)
1184 return (L_DNA *)ERROR_PTR("data & sequence not both defined",
1185 procName, NULL);
1186
1187 da = l_dnaCreate(0);
1188 start = 0;
1189 while (1) {
1190 arrayFindSequence(data + start, datalen - start, sequence, seqlen,
1191 &offset, &found);
1192 if (found == FALSE)
1193 break;
1194
1195 realoffset = start + offset;
1196 l_dnaAddNumber(da, realoffset);
1197 start = realoffset + seqlen;
1198 if (start >= datalen)
1199 break;
1200 }
1201
1202 if (l_dnaGetCount(da) == 0)
1203 l_dnaDestroy(&da);
1204 return da;
1205}
1206
1207
1232l_ok
1233arrayFindSequence(const l_uint8 *data,
1234 size_t datalen,
1235 const l_uint8 *sequence,
1236 size_t seqlen,
1237 l_int32 *poffset,
1238 l_int32 *pfound)
1239{
1240l_int32 i, j, found, lastpos;
1241
1242 PROCNAME("arrayFindSequence");
1243
1244 if (poffset) *poffset = 0;
1245 if (pfound) *pfound = FALSE;
1246 if (!data || !sequence)
1247 return ERROR_INT("data & sequence not both defined", procName, 1);
1248 if (!poffset || !pfound)
1249 return ERROR_INT("&offset and &found not defined", procName, 1);
1250
1251 lastpos = datalen - seqlen + 1;
1252 found = FALSE;
1253 for (i = 0; i < lastpos; i++) {
1254 for (j = 0; j < seqlen; j++) {
1255 if (data[i + j] != sequence[j])
1256 break;
1257 if (j == seqlen - 1)
1258 found = TRUE;
1259 }
1260 if (found == TRUE)
1261 break;
1262 }
1263
1264 if (found == TRUE) {
1265 *poffset = i;
1266 *pfound = TRUE;
1267 }
1268 return 0;
1269}
1270
1271
1272/*--------------------------------------------------------------------*
1273 * Safe realloc *
1274 *--------------------------------------------------------------------*/
1301void *
1302reallocNew(void **pindata,
1303 size_t oldsize,
1304 size_t newsize)
1305{
1306size_t minsize;
1307void *indata;
1308void *newdata;
1309
1310 PROCNAME("reallocNew");
1311
1312 if (!pindata)
1313 return ERROR_PTR("input data not defined", procName, NULL);
1314 indata = *pindata;
1315
1316 if (newsize == 0) { /* nonstandard usage */
1317 if (indata) {
1318 LEPT_FREE(indata);
1319 *pindata = NULL;
1320 }
1321 return NULL;
1322 }
1323
1324 if (!indata) { /* nonstandard usage */
1325 if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1326 return ERROR_PTR("newdata not made", procName, NULL);
1327 return newdata;
1328 }
1329
1330 /* Standard usage */
1331 if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1332 return ERROR_PTR("newdata not made", procName, NULL);
1333 minsize = L_MIN(oldsize, newsize);
1334 memcpy(newdata, indata, minsize);
1335 LEPT_FREE(indata);
1336 *pindata = NULL;
1337 return newdata;
1338}
1339
1340
1341/*--------------------------------------------------------------------*
1342 * Read and write between file and memory *
1343 *--------------------------------------------------------------------*/
1351l_uint8 *
1352l_binaryRead(const char *filename,
1353 size_t *pnbytes)
1354{
1355l_uint8 *data;
1356FILE *fp;
1357
1358 PROCNAME("l_binaryRead");
1359
1360 if (!pnbytes)
1361 return (l_uint8 *)ERROR_PTR("pnbytes not defined", procName, NULL);
1362 *pnbytes = 0;
1363 if (!filename)
1364 return (l_uint8 *)ERROR_PTR("filename not defined", procName, NULL);
1365
1366 if ((fp = fopenReadStream(filename)) == NULL)
1367 return (l_uint8 *)ERROR_PTR("file stream not opened", procName, NULL);
1368 data = l_binaryReadStream(fp, pnbytes);
1369 fclose(fp);
1370 return data;
1371}
1372
1373
1401l_uint8 *
1403 size_t *pnbytes)
1404{
1405l_uint8 *data;
1406l_int32 seekable, navail, nadd, nread;
1407L_BBUFFER *bb;
1408
1409 PROCNAME("l_binaryReadStream");
1410
1411 if (!pnbytes)
1412 return (l_uint8 *)ERROR_PTR("&nbytes not defined", procName, NULL);
1413 *pnbytes = 0;
1414 if (!fp)
1415 return (l_uint8 *)ERROR_PTR("fp not defined", procName, NULL);
1416
1417 /* Test if the stream is seekable, by attempting to seek to
1418 * the start of data. This is a no-op. If it is seekable, use
1419 * l_binaryReadSelectStream() to determine the size of the
1420 * data to be read in advance. */
1421 seekable = (ftell(fp) == 0) ? 1 : 0;
1422 if (seekable)
1423 return l_binaryReadSelectStream(fp, 0, 0, pnbytes);
1424
1425 /* If it is not seekable, use the bbuffer to realloc memory
1426 * as needed during reading. */
1427 bb = bbufferCreate(NULL, 4096);
1428 while (1) {
1429 navail = bb->nalloc - bb->n;
1430 if (navail < 4096) {
1431 nadd = L_MAX(bb->nalloc, 4096);
1432 bbufferExtendArray(bb, nadd);
1433 }
1434 nread = fread((void *)(bb->array + bb->n), 1, 4096, fp);
1435 bb->n += nread;
1436 if (nread != 4096) break;
1437 }
1438
1439 /* Copy the data to a new array sized for the data, because
1440 * the bbuffer array can be nearly twice the size we need. */
1441 if ((data = (l_uint8 *)LEPT_CALLOC(bb->n + 1, sizeof(l_uint8))) != NULL) {
1442 memcpy(data, bb->array, bb->n);
1443 *pnbytes = bb->n;
1444 } else {
1445 L_ERROR("calloc fail for data\n", procName);
1446 }
1447
1448 bbufferDestroy(&bb);
1449 return data;
1450}
1451
1452
1468l_uint8 *
1469l_binaryReadSelect(const char *filename,
1470 size_t start,
1471 size_t nbytes,
1472 size_t *pnread)
1473{
1474l_uint8 *data;
1475FILE *fp;
1476
1477 PROCNAME("l_binaryReadSelect");
1478
1479 if (!pnread)
1480 return (l_uint8 *)ERROR_PTR("pnread not defined", procName, NULL);
1481 *pnread = 0;
1482 if (!filename)
1483 return (l_uint8 *)ERROR_PTR("filename not defined", procName, NULL);
1484
1485 if ((fp = fopenReadStream(filename)) == NULL)
1486 return (l_uint8 *)ERROR_PTR("file stream not opened", procName, NULL);
1487 data = l_binaryReadSelectStream(fp, start, nbytes, pnread);
1488 fclose(fp);
1489 return data;
1490}
1491
1492
1513l_uint8 *
1515 size_t start,
1516 size_t nbytes,
1517 size_t *pnread)
1518{
1519l_uint8 *data;
1520size_t bytesleft, bytestoread, nread, filebytes;
1521
1522 PROCNAME("l_binaryReadSelectStream");
1523
1524 if (!pnread)
1525 return (l_uint8 *)ERROR_PTR("&nread not defined", procName, NULL);
1526 *pnread = 0;
1527 if (!fp)
1528 return (l_uint8 *)ERROR_PTR("stream not defined", procName, NULL);
1529
1530 /* Verify and adjust the parameters if necessary */
1531 fseek(fp, 0, SEEK_END); /* EOF */
1532 filebytes = ftell(fp);
1533 fseek(fp, 0, SEEK_SET);
1534 if (start > filebytes) {
1535 L_ERROR("start = %zu but filebytes = %zu\n", procName,
1536 start, filebytes);
1537 return NULL;
1538 }
1539 if (filebytes == 0) /* start == 0; nothing to read; return null byte */
1540 return (l_uint8 *)LEPT_CALLOC(1, 1);
1541 bytesleft = filebytes - start; /* greater than 0 */
1542 if (nbytes == 0) nbytes = bytesleft;
1543 bytestoread = (bytesleft >= nbytes) ? nbytes : bytesleft;
1544
1545 /* Read the data */
1546 if ((data = (l_uint8 *)LEPT_CALLOC(1, bytestoread + 1)) == NULL)
1547 return (l_uint8 *)ERROR_PTR("calloc fail for data", procName, NULL);
1548 fseek(fp, start, SEEK_SET);
1549 nread = fread(data, 1, bytestoread, fp);
1550 if (nbytes != nread)
1551 L_INFO("%zu bytes requested; %zu bytes read\n", procName,
1552 nbytes, nread);
1553 *pnread = nread;
1554 fseek(fp, 0, SEEK_SET);
1555 return data;
1556}
1557
1558
1568l_ok
1569l_binaryWrite(const char *filename,
1570 const char *operation,
1571 const void *data,
1572 size_t nbytes)
1573{
1574char actualOperation[20];
1575FILE *fp;
1576
1577 PROCNAME("l_binaryWrite");
1578
1579 if (!filename)
1580 return ERROR_INT("filename not defined", procName, 1);
1581 if (!operation)
1582 return ERROR_INT("operation not defined", procName, 1);
1583 if (!data)
1584 return ERROR_INT("data not defined", procName, 1);
1585 if (nbytes <= 0)
1586 return ERROR_INT("nbytes must be > 0", procName, 1);
1587
1588 if (strcmp(operation, "w") && strcmp(operation, "a"))
1589 return ERROR_INT("operation not one of {'w','a'}", procName, 1);
1590
1591 /* The 'b' flag to fopen() is ignored for all POSIX
1592 * conforming systems. However, Windows needs the 'b' flag. */
1593 stringCopy(actualOperation, operation, 2);
1594 stringCat(actualOperation, 20, "b");
1595
1596 if ((fp = fopenWriteStream(filename, actualOperation)) == NULL)
1597 return ERROR_INT("stream not opened", procName, 1);
1598 fwrite(data, 1, nbytes, fp);
1599 fclose(fp);
1600 return 0;
1601}
1602
1603
1610size_t
1611nbytesInFile(const char *filename)
1612{
1613size_t nbytes;
1614FILE *fp;
1615
1616 PROCNAME("nbytesInFile");
1617
1618 if (!filename)
1619 return ERROR_INT("filename not defined", procName, 0);
1620 if ((fp = fopenReadStream(filename)) == NULL)
1621 return ERROR_INT("stream not opened", procName, 0);
1622 nbytes = fnbytesInFile(fp);
1623 fclose(fp);
1624 return nbytes;
1625}
1626
1627
1634size_t
1636{
1637l_int64 pos, nbytes;
1638
1639 PROCNAME("fnbytesInFile");
1640
1641 if (!fp)
1642 return ERROR_INT("stream not open", procName, 0);
1643
1644 pos = ftell(fp); /* initial position */
1645 if (pos < 0)
1646 return ERROR_INT("seek position must be > 0", procName, 0);
1647 fseek(fp, 0, SEEK_END); /* EOF */
1648 nbytes = ftell(fp);
1649 if (nbytes < 0)
1650 return ERROR_INT("nbytes is < 0", procName, 0);
1651 fseek(fp, pos, SEEK_SET); /* back to initial position */
1652 return nbytes;
1653}
1654
1655
1656/*--------------------------------------------------------------------*
1657 * Copy and compare in memory *
1658 *--------------------------------------------------------------------*/
1674l_uint8 *
1675l_binaryCopy(const l_uint8 *datas,
1676 size_t size)
1677{
1678l_uint8 *datad;
1679
1680 PROCNAME("l_binaryCopy");
1681
1682 if (!datas)
1683 return (l_uint8 *)ERROR_PTR("datas not defined", procName, NULL);
1684
1685 if ((datad = (l_uint8 *)LEPT_CALLOC(size + 4, sizeof(l_uint8))) == NULL)
1686 return (l_uint8 *)ERROR_PTR("datad not made", procName, NULL);
1687 memcpy(datad, datas, size);
1688 return datad;
1689}
1690
1691
1710l_ok
1711l_binaryCompare(const l_uint8 *data1,
1712 size_t size1,
1713 const l_uint8 *data2,
1714 size_t size2,
1715 l_int32 *psame)
1716{
1717l_int32 i;
1718
1719 PROCNAME("l_binaryCompare");
1720
1721 if (!psame)
1722 return ERROR_INT("&same not defined", procName, 1);
1723 *psame = FALSE;
1724 if (!data1 || !data2)
1725 return ERROR_INT("data1 and data2 not both defined", procName, 1);
1726 if (size1 != size2) return 0;
1727 for (i = 0; i < size1; i++) {
1728 if (data1[i] != data2[i])
1729 return 0;
1730 }
1731 *psame = TRUE;
1732 return 0;
1733}
1734
1735
1736/*--------------------------------------------------------------------*
1737 * File copy operations *
1738 *--------------------------------------------------------------------*/
1746l_ok
1747fileCopy(const char *srcfile,
1748 const char *newfile)
1749{
1750l_int32 ret;
1751size_t nbytes;
1752l_uint8 *data;
1753
1754 PROCNAME("fileCopy");
1755
1756 if (!srcfile)
1757 return ERROR_INT("srcfile not defined", procName, 1);
1758 if (!newfile)
1759 return ERROR_INT("newfile not defined", procName, 1);
1760
1761 if ((data = l_binaryRead(srcfile, &nbytes)) == NULL)
1762 return ERROR_INT("data not returned", procName, 1);
1763 ret = l_binaryWrite(newfile, "w", data, nbytes);
1764 LEPT_FREE(data);
1765 return ret;
1766}
1767
1768
1776l_ok
1777fileConcatenate(const char *srcfile,
1778 const char *destfile)
1779{
1780size_t nbytes;
1781l_uint8 *data;
1782
1783 PROCNAME("fileConcatenate");
1784
1785 if (!srcfile)
1786 return ERROR_INT("srcfile not defined", procName, 1);
1787 if (!destfile)
1788 return ERROR_INT("destfile not defined", procName, 1);
1789
1790 data = l_binaryRead(srcfile, &nbytes);
1791 l_binaryWrite(destfile, "a", data, nbytes);
1792 LEPT_FREE(data);
1793 return 0;
1794}
1795
1796
1804l_ok
1805fileAppendString(const char *filename,
1806 const char *str)
1807{
1808FILE *fp;
1809
1810 PROCNAME("fileAppendString");
1811
1812 if (!filename)
1813 return ERROR_INT("filename not defined", procName, 1);
1814 if (!str)
1815 return ERROR_INT("str not defined", procName, 1);
1816
1817 if ((fp = fopenWriteStream(filename, "a")) == NULL)
1818 return ERROR_INT("stream not opened", procName, 1);
1819 fprintf(fp, "%s", str);
1820 fclose(fp);
1821 return 0;
1822}
1823
1824
1825/*--------------------------------------------------------------------*
1826 * File split operations *
1827 *--------------------------------------------------------------------*/
1854l_ok
1855fileSplitLinesUniform(const char *filename,
1856 l_int32 n,
1857 l_int32 save_empty,
1858 const char *rootpath,
1859 const char *ext)
1860{
1861l_int32 i, totlines, nlines, index;
1862size_t nbytes;
1863l_uint8 *data;
1864char *str;
1865char outname[512];
1866NUMA *na;
1867SARRAY *sa;
1868
1869 PROCNAME("fileSplitLinesUniform");
1870
1871 if (!filename)
1872 return ERROR_INT("filename not defined", procName, 1);
1873 if (!rootpath)
1874 return ERROR_INT("rootpath not defined", procName, 1);
1875 if (n <= 0)
1876 return ERROR_INT("n must be > 0", procName, 1);
1877 if (save_empty != 0 && save_empty != 1)
1878 return ERROR_INT("save_empty not 0 or 1", procName, 1);
1879
1880 /* Make sarray of lines; the newlines are stripped off */
1881 if ((data = l_binaryRead(filename, &nbytes)) == NULL)
1882 return ERROR_INT("data not read", procName, 1);
1883 sa = sarrayCreateLinesFromString((const char *)data, save_empty);
1884 LEPT_FREE(data);
1885 if (!sa)
1886 return ERROR_INT("sa not made", procName, 1);
1887 totlines = sarrayGetCount(sa);
1888 if (n > totlines) {
1889 sarrayDestroy(&sa);
1890 L_ERROR("num files = %d > num lines = %d\n", procName, n, totlines);
1891 return 1;
1892 }
1893
1894 /* Write n sets of lines to n files, adding the newlines back */
1895 na = numaGetUniformBinSizes(totlines, n);
1896 index = 0;
1897 for (i = 0; i < n; i++) {
1898 if (ext == NULL)
1899 snprintf(outname, sizeof(outname), "%s_%d", rootpath, i);
1900 else
1901 snprintf(outname, sizeof(outname), "%s_%d%s", rootpath, i, ext);
1902 numaGetIValue(na, i, &nlines);
1903 str = sarrayToStringRange(sa, index, nlines, 1); /* add newlines */
1904 l_binaryWrite(outname, "w", str, strlen(str));
1905 LEPT_FREE(str);
1906 index += nlines;
1907 }
1908 numaDestroy(&na);
1909 sarrayDestroy(&sa);
1910 return 0;
1911}
1912
1913
1914/*--------------------------------------------------------------------*
1915 * Multi-platform functions for opening file streams *
1916 *--------------------------------------------------------------------*/
1931FILE *
1932fopenReadStream(const char *filename)
1933{
1934char *fname, *tail;
1935FILE *fp;
1936
1937 PROCNAME("fopenReadStream");
1938
1939 if (!filename)
1940 return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
1941
1942 /* Try input filename */
1943 fname = genPathname(filename, NULL);
1944 fp = fopen(fname, "rb");
1945 LEPT_FREE(fname);
1946 if (fp) return fp;
1947
1948 /* Else, strip directory and try locally */
1949 splitPathAtDirectory(filename, NULL, &tail);
1950 fp = fopen(tail, "rb");
1951 LEPT_FREE(tail);
1952
1953 if (!fp)
1954 return (FILE *)ERROR_PTR("file not found", procName, NULL);
1955 return fp;
1956}
1957
1958
1974FILE *
1975fopenWriteStream(const char *filename,
1976 const char *modestring)
1977{
1978char *fname;
1979FILE *fp;
1980
1981 PROCNAME("fopenWriteStream");
1982
1983 if (!filename)
1984 return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
1985
1986 fname = genPathname(filename, NULL);
1987 fp = fopen(fname, modestring);
1988 LEPT_FREE(fname);
1989 if (!fp)
1990 return (FILE *)ERROR_PTR("stream not opened", procName, NULL);
1991 return fp;
1992}
1993
1994
2008FILE *
2009fopenReadFromMemory(const l_uint8 *data,
2010 size_t size)
2011{
2012FILE *fp;
2013
2014 PROCNAME("fopenReadFromMemory");
2015
2016 if (!data)
2017 return (FILE *)ERROR_PTR("data not defined", procName, NULL);
2018
2019#if HAVE_FMEMOPEN
2020 if ((fp = fmemopen((void *)data, size, "rb")) == NULL)
2021 return (FILE *)ERROR_PTR("stream not opened", procName, NULL);
2022#else /* write to tmp file */
2023 L_INFO("work-around: writing to a temp file\n", procName);
2024 #ifdef _WIN32
2025 if ((fp = fopenWriteWinTempfile()) == NULL)
2026 return (FILE *)ERROR_PTR("tmpfile stream not opened", procName, NULL);
2027 #else
2028 if ((fp = tmpfile()) == NULL)
2029 return (FILE *)ERROR_PTR("tmpfile stream not opened", procName, NULL);
2030 #endif /* _WIN32 */
2031 fwrite(data, 1, size, fp);
2032 rewind(fp);
2033#endif /* HAVE_FMEMOPEN */
2034
2035 return fp;
2036}
2037
2038
2039/*--------------------------------------------------------------------*
2040 * Opening a windows tmpfile for writing *
2041 *--------------------------------------------------------------------*/
2054FILE *
2056{
2057#ifdef _WIN32
2058l_int32 handle;
2059FILE *fp;
2060char *filename;
2061
2062 PROCNAME("fopenWriteWinTempfile");
2063
2064 if ((filename = l_makeTempFilename()) == NULL) {
2065 L_ERROR("l_makeTempFilename failed, %s\n", procName, strerror(errno));
2066 return NULL;
2067 }
2068
2069 handle = _open(filename, _O_CREAT | _O_RDWR | _O_SHORT_LIVED |
2070 _O_TEMPORARY | _O_BINARY, _S_IREAD | _S_IWRITE);
2071 lept_free(filename);
2072 if (handle == -1) {
2073 L_ERROR("_open failed, %s\n", procName, strerror(errno));
2074 return NULL;
2075 }
2076
2077 if ((fp = _fdopen(handle, "r+b")) == NULL) {
2078 L_ERROR("_fdopen failed, %s\n", procName, strerror(errno));
2079 return NULL;
2080 }
2081
2082 return fp;
2083#else
2084 return NULL;
2085#endif /* _WIN32 */
2086}
2087
2088
2089/*--------------------------------------------------------------------*
2090 * Multi-platform functions that avoid C-runtime boundary *
2091 * crossing for applications with Windows DLLs *
2092 *--------------------------------------------------------------------*/
2093/*
2094 * Problems arise when pointers to streams and data are passed
2095 * between two Windows DLLs that have been generated with different
2096 * C runtimes. To avoid this, leptonica provides wrappers for
2097 * several C library calls.
2098 */
2112FILE *
2113lept_fopen(const char *filename,
2114 const char *mode)
2115{
2116 PROCNAME("lept_fopen");
2117
2118 if (!filename)
2119 return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
2120 if (!mode)
2121 return (FILE *)ERROR_PTR("mode not defined", procName, NULL);
2122
2123 if (stringFindSubstr(mode, "r", NULL))
2124 return fopenReadStream(filename);
2125 else
2126 return fopenWriteStream(filename, mode);
2127}
2128
2129
2142l_ok
2144{
2145 PROCNAME("lept_fclose");
2146
2147 if (!fp)
2148 return ERROR_INT("stream not defined", procName, 1);
2149
2150 return fclose(fp);
2151}
2152
2153
2168void *
2169lept_calloc(size_t nmemb,
2170 size_t size)
2171{
2172 if (nmemb <= 0 || size <= 0)
2173 return NULL;
2174 return LEPT_CALLOC(nmemb, size);
2175}
2176
2177
2189void
2190lept_free(void *ptr)
2191{
2192 if (!ptr) return;
2193 LEPT_FREE(ptr);
2194}
2195
2196
2197/*--------------------------------------------------------------------*
2198 * Multi-platform file system operations *
2199 * [ These only write to /tmp or its subdirectories ] *
2200 *--------------------------------------------------------------------*/
2217l_int32
2218lept_mkdir(const char *subdir)
2219{
2220char *dir, *tmpdir;
2221l_int32 i, n;
2222l_int32 ret = 0;
2223SARRAY *sa;
2224#ifdef _WIN32
2225l_uint32 attributes;
2226#endif /* _WIN32 */
2227
2228 PROCNAME("lept_mkdir");
2229
2230 if (!LeptDebugOK) {
2231 L_INFO("making named temp subdirectory %s is disabled\n",
2232 procName, subdir);
2233 return 0;
2234 }
2235
2236 if (!subdir)
2237 return ERROR_INT("subdir not defined", procName, 1);
2238 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2239 return ERROR_INT("subdir not an actual subdirectory", procName, 1);
2240
2241 sa = sarrayCreate(0);
2242 sarraySplitString(sa, subdir, "/");
2243 n = sarrayGetCount(sa);
2244 dir = genPathname("/tmp", NULL);
2245 /* Make sure the tmp directory exists */
2246#ifndef _WIN32
2247 ret = mkdir(dir, 0777);
2248#else
2249 attributes = GetFileAttributes(dir);
2250 if (attributes == INVALID_FILE_ATTRIBUTES)
2251 ret = (CreateDirectory(dir, NULL) ? 0 : 1);
2252#endif
2253 /* Make all the subdirectories */
2254 for (i = 0; i < n; i++) {
2255 tmpdir = pathJoin(dir, sarrayGetString(sa, i, L_NOCOPY));
2256#ifndef _WIN32
2257 ret += mkdir(tmpdir, 0777);
2258#else
2259 if (CreateDirectory(tmpdir, NULL) == 0)
2260 ret += (GetLastError () != ERROR_ALREADY_EXISTS);
2261#endif
2262 LEPT_FREE(dir);
2263 dir = tmpdir;
2264 }
2265 LEPT_FREE(dir);
2266 sarrayDestroy(&sa);
2267 if (ret > 0)
2268 L_ERROR("failure to create %d directories\n", procName, ret);
2269 return ret;
2270}
2271
2272
2294l_int32
2295lept_rmdir(const char *subdir)
2296{
2297char *dir, *realdir, *fname, *fullname;
2298l_int32 exists, ret, i, nfiles;
2299SARRAY *sa;
2300#ifdef _WIN32
2301char *newpath;
2302#endif /* _WIN32 */
2303
2304 PROCNAME("lept_rmdir");
2305
2306 if (!subdir)
2307 return ERROR_INT("subdir not defined", procName, 1);
2308 if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2309 return ERROR_INT("subdir not an actual subdirectory", procName, 1);
2310
2311 /* Find the temp subdirectory */
2312 dir = pathJoin("/tmp", subdir);
2313 if (!dir)
2314 return ERROR_INT("directory name not made", procName, 1);
2315 lept_direxists(dir, &exists);
2316 if (!exists) { /* fail silently */
2317 LEPT_FREE(dir);
2318 return 0;
2319 }
2320
2321 /* List all the files in that directory */
2322 if ((sa = getFilenamesInDirectory(dir)) == NULL) {
2323 L_ERROR("directory %s does not exist!\n", procName, dir);
2324 LEPT_FREE(dir);
2325 return 1;
2326 }
2327 nfiles = sarrayGetCount(sa);
2328
2329 for (i = 0; i < nfiles; i++) {
2330 fname = sarrayGetString(sa, i, L_NOCOPY);
2331 fullname = genPathname(dir, fname);
2332 remove(fullname);
2333 LEPT_FREE(fullname);
2334 }
2335
2336#ifndef _WIN32
2337 realdir = genPathname("/tmp", subdir);
2338 ret = rmdir(realdir);
2339 LEPT_FREE(realdir);
2340#else
2341 newpath = genPathname(dir, NULL);
2342 ret = (RemoveDirectory(newpath) ? 0 : 1);
2343 LEPT_FREE(newpath);
2344#endif /* !_WIN32 */
2345
2346 sarrayDestroy(&sa);
2347 LEPT_FREE(dir);
2348 return ret;
2349}
2350
2351
2368void
2369lept_direxists(const char *dir,
2370 l_int32 *pexists)
2371{
2372char *realdir;
2373
2374 if (!pexists) return;
2375 *pexists = 0;
2376 if (!dir) return;
2377 if ((realdir = genPathname(dir, NULL)) == NULL)
2378 return;
2379
2380#ifndef _WIN32
2381 {
2382 struct stat s;
2383 l_int32 err = stat(realdir, &s);
2384 if (err != -1 && S_ISDIR(s.st_mode))
2385 *pexists = 1;
2386 }
2387#else /* _WIN32 */
2388 {
2389 l_uint32 attributes;
2390 attributes = GetFileAttributes(realdir);
2391 if (attributes != INVALID_FILE_ATTRIBUTES &&
2392 (attributes & FILE_ATTRIBUTE_DIRECTORY))
2393 *pexists = 1;
2394 }
2395#endif /* _WIN32 */
2396
2397 LEPT_FREE(realdir);
2398}
2399
2400
2426l_int32
2427lept_rm_match(const char *subdir,
2428 const char *substr)
2429{
2430char *path, *fname;
2431char tempdir[256];
2432l_int32 i, n, ret;
2433SARRAY *sa;
2434
2435 PROCNAME("lept_rm_match");
2436
2437 makeTempDirname(tempdir, sizeof(tempdir), subdir);
2438 if ((sa = getSortedPathnamesInDirectory(tempdir, substr, 0, 0)) == NULL)
2439 return ERROR_INT("sa not made", procName, -1);
2440 n = sarrayGetCount(sa);
2441 if (n == 0) {
2442 L_WARNING("no matching files found\n", procName);
2443 sarrayDestroy(&sa);
2444 return 0;
2445 }
2446
2447 ret = 0;
2448 for (i = 0; i < n; i++) {
2449 fname = sarrayGetString(sa, i, L_NOCOPY);
2450 path = genPathname(fname, NULL);
2451 if (lept_rmfile(path) != 0) {
2452 L_ERROR("failed to remove %s\n", procName, path);
2453 ret++;
2454 }
2455 LEPT_FREE(path);
2456 }
2457 sarrayDestroy(&sa);
2458 return ret;
2459}
2460
2461
2476l_int32
2477lept_rm(const char *subdir,
2478 const char *tail)
2479{
2480char *path;
2481char newtemp[256];
2482l_int32 ret;
2483
2484 PROCNAME("lept_rm");
2485
2486 if (!tail || strlen(tail) == 0)
2487 return ERROR_INT("tail undefined or empty", procName, 1);
2488
2489 if (makeTempDirname(newtemp, sizeof(newtemp), subdir))
2490 return ERROR_INT("temp dirname not made", procName, 1);
2491 path = genPathname(newtemp, tail);
2492 ret = lept_rmfile(path);
2493 LEPT_FREE(path);
2494 return ret;
2495}
2496
2497
2516l_int32
2517lept_rmfile(const char *filepath)
2518{
2519l_int32 ret;
2520
2521 PROCNAME("lept_rmfile");
2522
2523 if (!filepath || strlen(filepath) == 0)
2524 return ERROR_INT("filepath undefined or empty", procName, 1);
2525
2526#ifndef _WIN32
2527 ret = remove(filepath);
2528#else
2529 /* Set attributes to allow deletion of read-only files */
2530 SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL);
2531 ret = DeleteFile(filepath) ? 0 : 1;
2532#endif /* !_WIN32 */
2533
2534 return ret;
2535}
2536
2537
2571l_int32
2572lept_mv(const char *srcfile,
2573 const char *newdir,
2574 const char *newtail,
2575 char **pnewpath)
2576{
2577char *srcpath, *newpath, *dir, *srctail;
2578char newtemp[256];
2579l_int32 ret;
2580
2581 PROCNAME("lept_mv");
2582
2583 if (!srcfile)
2584 return ERROR_INT("srcfile not defined", procName, 1);
2585
2586 /* Require output pathname to be in /tmp/ or a subdirectory */
2587 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2588 return ERROR_INT("newdir not NULL or a subdir of /tmp", procName, 1);
2589
2590 /* Get canonical src pathname */
2591 splitPathAtDirectory(srcfile, &dir, &srctail);
2592
2593#ifndef _WIN32
2594 srcpath = pathJoin(dir, srctail);
2595 LEPT_FREE(dir);
2596
2597 /* Generate output pathname */
2598 if (!newtail || newtail[0] == '\0')
2599 newpath = pathJoin(newtemp, srctail);
2600 else
2601 newpath = pathJoin(newtemp, newtail);
2602 LEPT_FREE(srctail);
2603
2604 /* Overwrite any existing file at 'newpath' */
2605 ret = fileCopy(srcpath, newpath);
2606 if (!ret) { /* and remove srcfile */
2607 char *realpath = genPathname(srcpath, NULL);
2608 remove(realpath);
2609 LEPT_FREE(realpath);
2610 }
2611#else
2612 srcpath = genPathname(dir, srctail);
2613 LEPT_FREE(dir);
2614
2615 /* Generate output pathname */
2616 if (!newtail || newtail[0] == '\0')
2617 newpath = genPathname(newtemp, srctail);
2618 else
2619 newpath = genPathname(newtemp, newtail);
2620 LEPT_FREE(srctail);
2621
2622 /* Overwrite any existing file at 'newpath' */
2623 ret = MoveFileEx(srcpath, newpath,
2624 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) ? 0 : 1;
2625#endif /* ! _WIN32 */
2626
2627 LEPT_FREE(srcpath);
2628 if (pnewpath)
2629 *pnewpath = newpath;
2630 else
2631 LEPT_FREE(newpath);
2632 return ret;
2633}
2634
2635
2670l_int32
2671lept_cp(const char *srcfile,
2672 const char *newdir,
2673 const char *newtail,
2674 char **pnewpath)
2675{
2676char *srcpath, *newpath, *dir, *srctail;
2677char newtemp[256];
2678l_int32 ret;
2679
2680 PROCNAME("lept_cp");
2681
2682 if (!srcfile)
2683 return ERROR_INT("srcfile not defined", procName, 1);
2684
2685 /* Require output pathname to be in /tmp or a subdirectory */
2686 if (makeTempDirname(newtemp, sizeof(newtemp), newdir) == 1)
2687 return ERROR_INT("newdir not NULL or a subdir of /tmp", procName, 1);
2688
2689 /* Get canonical src pathname */
2690 splitPathAtDirectory(srcfile, &dir, &srctail);
2691
2692#ifndef _WIN32
2693 srcpath = pathJoin(dir, srctail);
2694 LEPT_FREE(dir);
2695
2696 /* Generate output pathname */
2697 if (!newtail || newtail[0] == '\0')
2698 newpath = pathJoin(newtemp, srctail);
2699 else
2700 newpath = pathJoin(newtemp, newtail);
2701 LEPT_FREE(srctail);
2702
2703 /* Overwrite any existing file at 'newpath' */
2704 ret = fileCopy(srcpath, newpath);
2705#else
2706 srcpath = genPathname(dir, srctail);
2707 LEPT_FREE(dir);
2708
2709 /* Generate output pathname */
2710 if (!newtail || newtail[0] == '\0')
2711 newpath = genPathname(newtemp, srctail);
2712 else
2713 newpath = genPathname(newtemp, newtail);
2714 LEPT_FREE(srctail);
2715
2716 /* Overwrite any existing file at 'newpath' */
2717 ret = CopyFile(srcpath, newpath, FALSE) ? 0 : 1;
2718#endif /* !_WIN32 */
2719
2720 LEPT_FREE(srcpath);
2721 if (pnewpath)
2722 *pnewpath = newpath;
2723 else
2724 LEPT_FREE(newpath);
2725 return ret;
2726}
2727
2728
2729/*--------------------------------------------------------------------*
2730 * Special debug/test function for calling 'system' *
2731 *--------------------------------------------------------------------*/
2732#if defined(__APPLE__)
2733 #include "TargetConditionals.h"
2734#endif /* __APPLE__ */
2735
2751void
2752callSystemDebug(const char *cmd)
2753{
2754l_int32 ret;
2755
2756 PROCNAME("callSystemDebug");
2757
2758 if (!cmd) {
2759 L_ERROR("cmd not defined\n", procName);
2760 return;
2761 }
2762 if (LeptDebugOK == FALSE) {
2763 L_INFO("'system' calls are disabled\n", procName);
2764 return;
2765 }
2766
2767#if defined(__APPLE__) /* iOS 11 does not support system() */
2768
2769 #if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) /* Mac OS X */
2770 ret = system(cmd);
2771 #elif TARGET_OS_IPHONE || defined(OS_IOS) /* iOS */
2772 L_ERROR("iOS 11 does not support system()\n", procName);
2773 #endif /* TARGET_OS_OSX */
2774
2775#else /* ! __APPLE__ */
2776
2777 ret = system(cmd);
2778
2779#endif /* __APPLE__ */
2780}
2781
2782
2783/*--------------------------------------------------------------------*
2784 * General file name operations *
2785 *--------------------------------------------------------------------*/
2823l_ok
2824splitPathAtDirectory(const char *pathname,
2825 char **pdir,
2826 char **ptail)
2827{
2828char *cpathname, *lastslash;
2829
2830 PROCNAME("splitPathAtDirectory");
2831
2832 if (!pdir && !ptail)
2833 return ERROR_INT("null input for both strings", procName, 1);
2834 if (pdir) *pdir = NULL;
2835 if (ptail) *ptail = NULL;
2836 if (!pathname)
2837 return ERROR_INT("pathname not defined", procName, 1);
2838
2839 cpathname = stringNew(pathname);
2840 convertSepCharsInPath(cpathname, UNIX_PATH_SEPCHAR);
2841 lastslash = strrchr(cpathname, '/');
2842 if (lastslash) {
2843 if (ptail)
2844 *ptail = stringNew(lastslash + 1);
2845 if (pdir) {
2846 *(lastslash + 1) = '\0';
2847 *pdir = cpathname;
2848 } else {
2849 LEPT_FREE(cpathname);
2850 }
2851 } else { /* no directory */
2852 if (pdir)
2853 *pdir = stringNew("");
2854 if (ptail)
2855 *ptail = cpathname;
2856 else
2857 LEPT_FREE(cpathname);
2858 }
2859
2860 return 0;
2861}
2862
2863
2893l_ok
2894splitPathAtExtension(const char *pathname,
2895 char **pbasename,
2896 char **pextension)
2897{
2898char *tail, *dir, *lastdot;
2899char empty[4] = "";
2900
2901 PROCNAME("splitPathExtension");
2902
2903 if (!pbasename && !pextension)
2904 return ERROR_INT("null input for both strings", procName, 1);
2905 if (pbasename) *pbasename = NULL;
2906 if (pextension) *pextension = NULL;
2907 if (!pathname)
2908 return ERROR_INT("pathname not defined", procName, 1);
2909
2910 /* Split out the directory first */
2911 splitPathAtDirectory(pathname, &dir, &tail);
2912
2913 /* Then look for a "." in the tail part.
2914 * This way we ignore all "." in the directory. */
2915 if ((lastdot = strrchr(tail, '.'))) {
2916 if (pextension)
2917 *pextension = stringNew(lastdot);
2918 if (pbasename) {
2919 *lastdot = '\0';
2920 *pbasename = stringJoin(dir, tail);
2921 }
2922 } else {
2923 if (pextension)
2924 *pextension = stringNew(empty);
2925 if (pbasename)
2926 *pbasename = stringNew(pathname);
2927 }
2928 LEPT_FREE(dir);
2929 LEPT_FREE(tail);
2930 return 0;
2931}
2932
2933
2972char *
2973pathJoin(const char *dir,
2974 const char *fname)
2975{
2976const char *slash = "/";
2977char *str, *dest;
2978l_int32 i, n1, n2, emptydir;
2979size_t size;
2980SARRAY *sa1, *sa2;
2981L_BYTEA *ba;
2982
2983 PROCNAME("pathJoin");
2984
2985 if (!dir && !fname)
2986 return stringNew("");
2987 if (dir && strlen(dir) >= 2 && dir[0] == '.' && dir[1] == '.')
2988 return (char *)ERROR_PTR("dir starts with '..'", procName, NULL);
2989 if (fname && strlen(fname) >= 2 && fname[0] == '.' && fname[1] == '.')
2990 return (char *)ERROR_PTR("fname starts with '..'", procName, NULL);
2991
2992 sa1 = sarrayCreate(0);
2993 sa2 = sarrayCreate(0);
2994 ba = l_byteaCreate(4);
2995
2996 /* Process %dir */
2997 if (dir && strlen(dir) > 0) {
2998 if (dir[0] == '/')
2999 l_byteaAppendString(ba, slash);
3000 sarraySplitString(sa1, dir, "/"); /* removes all slashes */
3001 n1 = sarrayGetCount(sa1);
3002 for (i = 0; i < n1; i++) {
3003 str = sarrayGetString(sa1, i, L_NOCOPY);
3004 l_byteaAppendString(ba, str);
3005 l_byteaAppendString(ba, slash);
3006 }
3007 }
3008
3009 /* Special case to add leading slash: dir NULL or empty string */
3010 emptydir = dir && strlen(dir) == 0;
3011 if ((!dir || emptydir) && fname && strlen(fname) > 0 && fname[0] == '/')
3012 l_byteaAppendString(ba, slash);
3013
3014 /* Process %fname */
3015 if (fname && strlen(fname) > 0) {
3016 sarraySplitString(sa2, fname, "/");
3017 n2 = sarrayGetCount(sa2);
3018 for (i = 0; i < n2; i++) {
3019 str = sarrayGetString(sa2, i, L_NOCOPY);
3020 l_byteaAppendString(ba, str);
3021 l_byteaAppendString(ba, slash);
3022 }
3023 }
3024
3025 /* Remove trailing slash */
3026 dest = (char *)l_byteaCopyData(ba, &size);
3027 if (size > 1 && dest[size - 1] == '/')
3028 dest[size - 1] = '\0';
3029
3030 sarrayDestroy(&sa1);
3031 sarrayDestroy(&sa2);
3032 l_byteaDestroy(&ba);
3033 return dest;
3034}
3035
3036
3051char *
3052appendSubdirs(const char *basedir,
3053 const char *subdirs)
3054{
3055char *newdir;
3056size_t len1, len2, len3, len4;
3057
3058 PROCNAME("appendSubdirs");
3059
3060 if (!basedir || !subdirs)
3061 return (char *)ERROR_PTR("basedir and subdirs not both defined",
3062 procName, NULL);
3063
3064 len1 = strlen(basedir);
3065 len2 = strlen(subdirs);
3066 len3 = len1 + len2 + 8;
3067 if ((newdir = (char *)LEPT_CALLOC(len3, 1)) == NULL)
3068 return (char *)ERROR_PTR("newdir not made", procName, NULL);
3069 stringCat(newdir, len3, basedir);
3070 if (newdir[len1 - 1] != '/') /* add '/' if necessary */
3071 newdir[len1] = '/';
3072 if (subdirs[0] == '/') /* add subdirs, stripping leading '/' */
3073 stringCat(newdir, len3, subdirs + 1);
3074 else
3075 stringCat(newdir, len3, subdirs);
3076 len4 = strlen(newdir);
3077 if (newdir[len4 - 1] == '/') /* strip trailing '/' */
3078 newdir[len4 - 1] = '\0';
3079
3080 return newdir;
3081}
3082
3083
3084/*--------------------------------------------------------------------*
3085 * Special file name operations *
3086 *--------------------------------------------------------------------*/
3107l_ok
3109 l_int32 type)
3110{
3111l_int32 i;
3112size_t len;
3113
3114 PROCNAME("convertSepCharsInPath");
3115 if (!path)
3116 return ERROR_INT("path not defined", procName, 1);
3117 if (type != UNIX_PATH_SEPCHAR && type != WIN_PATH_SEPCHAR)
3118 return ERROR_INT("invalid type", procName, 1);
3119
3120 len = strlen(path);
3121 if (type == UNIX_PATH_SEPCHAR) {
3122#ifdef _WIN32 /* only convert on windows */
3123 for (i = 0; i < len; i++) {
3124 if (path[i] == '\\')
3125 path[i] = '/';
3126 }
3127#endif /* _WIN32 */
3128 } else { /* WIN_PATH_SEPCHAR */
3129 for (i = 0; i < len; i++) {
3130 if (path[i] == '/')
3131 path[i] = '\\';
3132 }
3133 }
3134 return 0;
3135}
3136
3137
3172char *
3173genPathname(const char *dir,
3174 const char *fname)
3175{
3176l_int32 is_win32 = FALSE;
3177char *cdir, *pathout;
3178l_int32 dirlen, namelen;
3179size_t size;
3180
3181 PROCNAME("genPathname");
3182
3183 if (!dir && !fname)
3184 return (char *)ERROR_PTR("no input", procName, NULL);
3185
3186 /* Handle the case where we start from the current directory */
3187 if (!dir || dir[0] == '\0') {
3188 if ((cdir = getcwd(NULL, 0)) == NULL)
3189 return (char *)ERROR_PTR("no current dir found", procName, NULL);
3190 } else {
3191 cdir = stringNew(dir);
3192 }
3193
3194 /* Convert to unix path separators, and remove the trailing
3195 * slash in the directory, except when dir == "/" */
3196 convertSepCharsInPath(cdir, UNIX_PATH_SEPCHAR);
3197 dirlen = strlen(cdir);
3198 if (cdir[dirlen - 1] == '/' && dirlen != 1) {
3199 cdir[dirlen - 1] = '\0';
3200 dirlen--;
3201 }
3202
3203 namelen = (fname) ? strlen(fname) : 0;
3204 size = dirlen + namelen + 256;
3205 if ((pathout = (char *)LEPT_CALLOC(size, sizeof(char))) == NULL) {
3206 LEPT_FREE(cdir);
3207 return (char *)ERROR_PTR("pathout not made", procName, NULL);
3208 }
3209
3210#ifdef _WIN32
3211 is_win32 = TRUE;
3212#endif /* _WIN32 */
3213
3214 /* First handle %dir (which may be a full pathname).
3215 * There is no path rewriting on unix, and on win32, we do not
3216 * rewrite unless the specified directory is /tmp or
3217 * a subdirectory of /tmp */
3218 if (!is_win32 || dirlen < 4 ||
3219 (dirlen == 4 && strncmp(cdir, "/tmp", 4) != 0) || /* not in "/tmp" */
3220 (dirlen > 4 && strncmp(cdir, "/tmp/", 5) != 0)) { /* not in "/tmp/" */
3221 stringCopy(pathout, cdir, dirlen);
3222 } else { /* Rewrite for win32 with "/tmp" specified for the directory. */
3223#ifdef _WIN32
3224 l_int32 tmpdirlen;
3225 char tmpdir[MAX_PATH];
3226 GetTempPath(sizeof(tmpdir), tmpdir); /* get the windows temp dir */
3227 tmpdirlen = strlen(tmpdir);
3228 if (tmpdirlen > 0 && tmpdir[tmpdirlen - 1] == '\\') {
3229 tmpdir[tmpdirlen - 1] = '\0'; /* trim the trailing '\' */
3230 }
3231 tmpdirlen = strlen(tmpdir);
3232 stringCopy(pathout, tmpdir, tmpdirlen);
3233
3234 /* Add the rest of cdir */
3235 if (dirlen > 4)
3236 stringCat(pathout, size, cdir + 4);
3237#endif /* _WIN32 */
3238 }
3239
3240 /* Now handle %fname */
3241 if (fname && strlen(fname) > 0) {
3242 dirlen = strlen(pathout);
3243 pathout[dirlen] = '/';
3244 stringCat(pathout, size, fname);
3245 }
3246
3247 LEPT_FREE(cdir);
3248 return pathout;
3249}
3250
3251
3281l_ok
3282makeTempDirname(char *result,
3283 size_t nbytes,
3284 const char *subdir)
3285{
3286char *dir, *path;
3287l_int32 ret = 0;
3288size_t pathlen;
3289
3290 PROCNAME("makeTempDirname");
3291
3292 if (!result)
3293 return ERROR_INT("result not defined", procName, 1);
3294 if (subdir && ((subdir[0] == '.') || (subdir[0] == '/')))
3295 return ERROR_INT("subdir not an actual subdirectory", procName, 1);
3296
3297 memset(result, 0, nbytes);
3298
3299#ifdef __APPLE__
3300 {
3301 size_t n = confstr(_CS_DARWIN_USER_TEMP_DIR, result, nbytes);
3302 if (n == 0) {
3303 L_ERROR("failed to find tmp dir, %s\n", procName, strerror(errno));
3304 return 1;
3305 } else if (n > nbytes) {
3306 return ERROR_INT("result array too small for path\n", procName, 1);
3307 }
3308 dir = pathJoin(result, subdir);
3309 }
3310#else
3311 dir = pathJoin("/tmp", subdir);
3312#endif /* ~ __APPLE__ */
3313
3314#ifndef _WIN32
3315 path = stringNew(dir);
3316#else
3317 path = genPathname(dir, NULL);
3318#endif /* ~ _WIN32 */
3319 pathlen = strlen(path);
3320 if (pathlen < nbytes - 1) {
3321 stringCopy(result, path, nbytes);
3322 } else {
3323 L_ERROR("result array too small for path\n", procName);
3324 ret = 1;
3325 }
3326
3327 LEPT_FREE(dir);
3328 LEPT_FREE(path);
3329 return ret;
3330}
3331
3332
3346l_ok
3348 size_t nbytes,
3349 l_int32 flag)
3350{
3351char lastchar;
3352size_t len;
3353
3354 PROCNAME("modifyTrailingSlash");
3355
3356 if (!path)
3357 return ERROR_INT("path not defined", procName, 1);
3358 if (flag != L_ADD_TRAIL_SLASH && flag != L_REMOVE_TRAIL_SLASH)
3359 return ERROR_INT("invalid flag", procName, 1);
3360
3361 len = strlen(path);
3362 lastchar = path[len - 1];
3363 if (flag == L_ADD_TRAIL_SLASH && lastchar != '/' && len < nbytes - 2) {
3364 path[len] = '/';
3365 path[len + 1] = '\0';
3366 } else if (flag == L_REMOVE_TRAIL_SLASH && lastchar == '/') {
3367 path[len - 1] = '\0';
3368 }
3369 return 0;
3370}
3371
3372
3396char *
3398{
3399char dirname[240];
3400
3401 PROCNAME("l_makeTempFilename");
3402
3403 if (makeTempDirname(dirname, sizeof(dirname), NULL) == 1)
3404 return (char *)ERROR_PTR("failed to make dirname", procName, NULL);
3405
3406#ifndef _WIN32
3407{
3408 char *pattern;
3409 l_int32 fd;
3410 pattern = stringConcatNew(dirname, "/lept.XXXXXX", NULL);
3411 fd = mkstemp(pattern);
3412 if (fd == -1) {
3413 LEPT_FREE(pattern);
3414 return (char *)ERROR_PTR("mkstemp failed", procName, NULL);
3415 }
3416 close(fd);
3417 return pattern;
3418}
3419#else
3420{
3421 char fname[MAX_PATH];
3422 FILE *fp;
3423 if (GetTempFileName(dirname, "lp.", 0, fname) == 0)
3424 return (char *)ERROR_PTR("GetTempFileName failed", procName, NULL);
3425 if ((fp = fopen(fname, "wb")) == NULL)
3426 return (char *)ERROR_PTR("file cannot be written to", procName, NULL);
3427 fclose(fp);
3428 return stringNew(fname);
3429}
3430#endif /* ~ _WIN32 */
3431}
3432
3433
3452l_int32
3454 l_int32 numpre,
3455 l_int32 numpost)
3456{
3457char *tail, *basename;
3458l_int32 len, nret, num;
3459
3460 PROCNAME("extractNumberFromFilename");
3461
3462 if (!fname)
3463 return ERROR_INT("fname not defined", procName, -1);
3464
3465 splitPathAtDirectory(fname, NULL, &tail);
3466 splitPathAtExtension(tail, &basename, NULL);
3467 LEPT_FREE(tail);
3468
3469 len = strlen(basename);
3470 if (numpre + numpost > len - 1) {
3471 LEPT_FREE(basename);
3472 return ERROR_INT("numpre + numpost too big", procName, -1);
3473 }
3474
3475 basename[len - numpost] = '\0';
3476 nret = sscanf(basename + numpre, "%d", &num);
3477 LEPT_FREE(basename);
3478
3479 if (nret == 1)
3480 return num;
3481 else
3482 return -1; /* not found */
3483}
L_BBUFFER * bbufferCreate(const l_uint8 *indata, l_int32 nalloc)
bbufferCreate()
Definition: bbuffer.c:130
l_ok bbufferExtendArray(L_BBUFFER *bb, l_int32 nbytes)
bbufferExtendArray()
Definition: bbuffer.c:363
void bbufferDestroy(L_BBUFFER **pbb)
bbufferDestroy()
Definition: bbuffer.c:172
L_BYTEA * l_byteaCreate(size_t nbytes)
l_byteaCreate()
Definition: bytearray.c:97
l_uint8 * l_byteaCopyData(L_BYTEA *ba, size_t *psize)
l_byteaCopyData()
Definition: bytearray.c:336
void l_byteaDestroy(L_BYTEA **pba)
l_byteaDestroy()
Definition: bytearray.c:250
l_ok l_byteaAppendString(L_BYTEA *ba, const char *str)
l_byteaAppendString()
Definition: bytearray.c:401
l_ok l_dnaGetIValue(L_DNA *da, l_int32 index, l_int32 *pival)
l_dnaGetIValue()
Definition: dnabasic.c:727
l_ok l_dnaAddNumber(L_DNA *da, l_float64 val)
l_dnaAddNumber()
Definition: dnabasic.c:448
L_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:180
void l_dnaDestroy(L_DNA **pda)
l_dnaDestroy()
Definition: dnabasic.c:332
l_int32 l_dnaGetCount(L_DNA *da)
l_dnaGetCount()
Definition: dnabasic.c:631
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
NUMA * numaGetUniformBinSizes(l_int32 ntotal, l_int32 nbins)
numaGetUniformBinSizes()
Definition: numafunc2.c:1945
@ L_NOCOPY
Definition: pix.h:710
@ L_ADD_TRAIL_SLASH
Definition: pix.h:1288
@ L_REMOVE_TRAIL_SLASH
Definition: pix.h:1289
SARRAY * getSortedPathnamesInDirectory(const char *dirname, const char *substr, l_int32 first, l_int32 nfiles)
getSortedPathnamesInDirectory()
Definition: sarray1.c:1848
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
char * sarrayToStringRange(SARRAY *sa, l_int32 first, l_int32 nstrings, l_int32 addnlflag)
sarrayToStringRange()
Definition: sarray1.c:820
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:703
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:643
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:362
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:283
SARRAY * getFilenamesInDirectory(const char *dirname)
getFilenamesInDirectory()
Definition: sarray1.c:1990
l_int32 n
Definition: bbuffer.h:53
l_int32 nalloc
Definition: bbuffer.h:52
l_uint8 * array
Definition: bbuffer.h:55
Definition: array.h:137
Definition: array.h:95
Definition: array.h:71
Definition: array.h:127
l_int32 stringLength(const char *src, size_t size)
stringLength()
Definition: utils2.c:381
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1611
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
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:2369
l_int32 lept_rm(const char *subdir, const char *tail)
lept_rm()
Definition: utils2.c:2477
l_ok lept_fclose(FILE *fp)
lept_fclose()
Definition: utils2.c:2143
char * stringReverse(const char *src)
stringReverse()
Definition: utils2.c:597
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2517
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2973
l_uint8 * l_binaryCopy(const l_uint8 *datas, size_t size)
l_binaryCopy()
Definition: utils2.c:1675
l_uint8 * l_binaryReadSelectStream(FILE *fp, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelectStream()
Definition: utils2.c:1514
l_ok fileAppendString(const char *filename, const char *str)
fileAppendString()
Definition: utils2.c:1805
l_int32 lept_rm_match(const char *subdir, const char *substr)
lept_rm_match()
Definition: utils2.c:2427
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:345
char * strtokSafe(char *cstr, const char *seps, char **psaveptr)
strtokSafe()
Definition: utils2.c:649
l_ok fileConcatenate(const char *srcfile, const char *destfile)
fileConcatenate()
Definition: utils2.c:1777
l_ok stringJoinIP(char **psrc1, const char *src2)
stringJoinIP()
Definition: utils2.c:573
char * stringRemoveChars(const char *src, const char *remchars)
stringRemoveChars()
Definition: utils2.c:822
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
void lept_free(void *ptr)
lept_free()
Definition: utils2.c:2190
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition: utils2.c:3397
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition: utils2.c:3347
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2894
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition: utils2.c:3173
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition: utils2.c:2752
l_int32 lept_cp(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_cp()
Definition: utils2.c:2671
l_int32 lept_mv(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_mv()
Definition: utils2.c:2572
l_ok stringCheckForChars(const char *src, const char *chars, l_int32 *pfound)
stringCheckForChars()
Definition: utils2.c:787
FILE * lept_fopen(const char *filename, const char *mode)
lept_fopen()
Definition: utils2.c:2113
char * stringReplaceEachSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *pcount)
stringReplaceEachSubstr()
Definition: utils2.c:878
char * stringConcatNew(const char *first,...)
stringConcatNew()
Definition: utils2.c:471
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:1711
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition: utils2.c:1635
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2824
l_uint8 * l_binaryReadSelect(const char *filename, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelect()
Definition: utils2.c:1469
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
l_int32 stringFindSubstr(const char *src, const char *sub, l_int32 *ploc)
stringFindSubstr()
Definition: utils2.c:1027
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition: utils2.c:518
l_ok convertSepCharsInPath(char *path, l_int32 type)
convertSepCharsInPath()
Definition: utils2.c:3108
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition: utils2.c:423
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402
char * stringReplaceSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *ploc, l_int32 *pfound)
stringReplaceSubstr()
Definition: utils2.c:935
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1302
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition: utils2.c:1173
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:1082
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition: utils2.c:3282
l_ok stringSplitOnToken(char *cstr, const char *seps, char **phead, char **ptail)
stringSplitOnToken()
Definition: utils2.c:743
void * lept_calloc(size_t nmemb, size_t size)
lept_calloc()
Definition: utils2.c:2169
L_DNA * stringFindEachSubstr(const char *src, const char *sub)
stringFindEachSubstr()
Definition: utils2.c:996
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_ok stringCopy(char *dest, const char *src, l_int32 n)
stringCopy()
Definition: utils2.c:263
l_ok fileSplitLinesUniform(const char *filename, l_int32 n, l_int32 save_empty, const char *rootpath, const char *ext)
fileSplitLinesUniform()
Definition: utils2.c:1855
l_int32 extractNumberFromFilename(const char *fname, l_int32 numpre, l_int32 numpost)
extractNumberFromFilename()
Definition: utils2.c:3453
char * appendSubdirs(const char *basedir, const char *subdirs)
appendSubdirs()
Definition: utils2.c:3052
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:1233
l_ok fileCopy(const char *srcfile, const char *newfile)
fileCopy()
Definition: utils2.c:1747