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