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  *--------------------------------------------------------------------*/
222 char *
223 stringNew(const char *src)
224 {
225 l_int32 len;
226 char *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 
262 l_ok
263 stringCopy(char *dest,
264  const char *src,
265  l_int32 n)
266 {
267 l_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 
304 char *
305 stringCopySegment(const char *src,
306  l_int32 start,
307  l_int32 nbytes)
308 {
309 char *dest;
310 l_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 
344 l_ok
345 stringReplace(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 
380 l_int32
381 stringLength(const char *src,
382  size_t size)
383 {
384 l_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 
422 l_int32
423 stringCat(char *dest,
424  size_t size,
425  const char *src)
426 {
427 l_int32 i, n;
428 l_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 
470 char *
471 stringConcatNew(const char *first, ...)
472 {
473 size_t len;
474 char *result, *ptr;
475 const char *arg;
476 va_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 
517 char *
518 stringJoin(const char *src1,
519  const char *src2)
520 {
521 char *dest;
522 l_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 
572 l_ok
573 stringJoinIP(char **psrc1,
574  const char *src2)
575 {
576 char *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 
596 char *
597 stringReverse(const char *src)
598 {
599 char *dest;
600 l_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 
648 char *
649 strtokSafe(char *cstr,
650  const char *seps,
651  char **psaveptr)
652 {
653 char nextc;
654 char *start, *substr;
655 l_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 
742 l_ok
744  const char *seps,
745  char **phead,
746  char **ptail)
747 {
748 char *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  *--------------------------------------------------------------------*/
786 l_ok
787 stringCheckForChars(const char *src,
788  const char *chars,
789  l_int32 *pfound)
790 {
791 char ch;
792 l_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 
821 char *
822 stringRemoveChars(const char *src,
823  const char *remchars)
824 {
825 char ch;
826 char *dest;
827 l_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 
877 char *
878 stringReplaceEachSubstr(const char *src,
879  const char *sub1,
880  const char *sub2,
881  l_int32 *pcount)
882 {
883 size_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 
934 char *
935 stringReplaceSubstr(const char *src,
936  const char *sub1,
937  const char *sub2,
938  l_int32 *ploc,
939  l_int32 *pfound)
940 {
941 const char *ptr;
942 char *dest;
943 l_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 
995 L_DNA *
996 stringFindEachSubstr(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 
1026 l_int32
1027 stringFindSubstr(const char *src,
1028  const char *sub,
1029  l_int32 *ploc)
1030 {
1031 const 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 
1081 l_uint8 *
1082 arrayReplaceEachSequence(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 {
1091 l_uint8 *datad;
1092 size_t newsize;
1093 l_int32 n, i, j, di, si, index, incr;
1094 L_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 
1172 L_DNA *
1173 arrayFindEachSequence(const l_uint8 *data,
1174  size_t datalen,
1175  const l_uint8 *sequence,
1176  size_t seqlen)
1177 {
1178 l_int32 start, offset, realoffset, found;
1179 L_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 
1232 l_ok
1233 arrayFindSequence(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 {
1240 l_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  *--------------------------------------------------------------------*/
1301 void *
1302 reallocNew(void **pindata,
1303  size_t oldsize,
1304  size_t newsize)
1305 {
1306 size_t minsize;
1307 void *indata;
1308 void *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  *--------------------------------------------------------------------*/
1351 l_uint8 *
1352 l_binaryRead(const char *filename,
1353  size_t *pnbytes)
1354 {
1355 l_uint8 *data;
1356 FILE *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 
1401 l_uint8 *
1403  size_t *pnbytes)
1404 {
1405 l_uint8 *data;
1406 l_int32 seekable, navail, nadd, nread;
1407 L_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 
1468 l_uint8 *
1469 l_binaryReadSelect(const char *filename,
1470  size_t start,
1471  size_t nbytes,
1472  size_t *pnread)
1473 {
1474 l_uint8 *data;
1475 FILE *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 
1513 l_uint8 *
1515  size_t start,
1516  size_t nbytes,
1517  size_t *pnread)
1518 {
1519 l_uint8 *data;
1520 size_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 
1568 l_ok
1569 l_binaryWrite(const char *filename,
1570  const char *operation,
1571  const void *data,
1572  size_t nbytes)
1573 {
1574 char actualOperation[20];
1575 FILE *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 
1610 size_t
1611 nbytesInFile(const char *filename)
1612 {
1613 size_t nbytes;
1614 FILE *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 
1634 size_t
1635 fnbytesInFile(FILE *fp)
1636 {
1637 l_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  *--------------------------------------------------------------------*/
1674 l_uint8 *
1675 l_binaryCopy(const l_uint8 *datas,
1676  size_t size)
1677 {
1678 l_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 
1710 l_ok
1711 l_binaryCompare(const l_uint8 *data1,
1712  size_t size1,
1713  const l_uint8 *data2,
1714  size_t size2,
1715  l_int32 *psame)
1716 {
1717 l_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  *--------------------------------------------------------------------*/
1746 l_ok
1747 fileCopy(const char *srcfile,
1748  const char *newfile)
1749 {
1750 l_int32 ret;
1751 size_t nbytes;
1752 l_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 
1776 l_ok
1777 fileConcatenate(const char *srcfile,
1778  const char *destfile)
1779 {
1780 size_t nbytes;
1781 l_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 
1804 l_ok
1805 fileAppendString(const char *filename,
1806  const char *str)
1807 {
1808 FILE *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  *--------------------------------------------------------------------*/
1854 l_ok
1855 fileSplitLinesUniform(const char *filename,
1856  l_int32 n,
1857  l_int32 save_empty,
1858  const char *rootpath,
1859  const char *ext)
1860 {
1861 l_int32 i, totlines, nlines, index;
1862 size_t nbytes;
1863 l_uint8 *data;
1864 char *str;
1865 char outname[512];
1866 NUMA *na;
1867 SARRAY *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  *--------------------------------------------------------------------*/
1931 FILE *
1932 fopenReadStream(const char *filename)
1933 {
1934 char *fname, *tail;
1935 FILE *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 
1974 FILE *
1975 fopenWriteStream(const char *filename,
1976  const char *modestring)
1977 {
1978 char *fname;
1979 FILE *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 
2008 FILE *
2009 fopenReadFromMemory(const l_uint8 *data,
2010  size_t size)
2011 {
2012 FILE *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  *--------------------------------------------------------------------*/
2054 FILE *
2056 {
2057 #ifdef _WIN32
2058 l_int32 handle;
2059 FILE *fp;
2060 char *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  */
2112 FILE *
2113 lept_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 
2142 l_ok
2143 lept_fclose(FILE *fp)
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 
2168 void *
2169 lept_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 
2189 void
2190 lept_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  *--------------------------------------------------------------------*/
2217 l_int32
2218 lept_mkdir(const char *subdir)
2219 {
2220 char *dir, *tmpdir;
2221 l_int32 i, n;
2222 l_int32 ret = 0;
2223 SARRAY *sa;
2224 #ifdef _WIN32
2225 l_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 
2294 l_int32
2295 lept_rmdir(const char *subdir)
2296 {
2297 char *dir, *realdir, *fname, *fullname;
2298 l_int32 exists, ret, i, nfiles;
2299 SARRAY *sa;
2300 #ifdef _WIN32
2301 char *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 
2368 void
2369 lept_direxists(const char *dir,
2370  l_int32 *pexists)
2371 {
2372 char *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 
2426 l_int32
2427 lept_rm_match(const char *subdir,
2428  const char *substr)
2429 {
2430 char *path, *fname;
2431 char tempdir[256];
2432 l_int32 i, n, ret;
2433 SARRAY *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 
2476 l_int32
2477 lept_rm(const char *subdir,
2478  const char *tail)
2479 {
2480 char *path;
2481 char newtemp[256];
2482 l_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 
2516 l_int32
2517 lept_rmfile(const char *filepath)
2518 {
2519 l_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 
2571 l_int32
2572 lept_mv(const char *srcfile,
2573  const char *newdir,
2574  const char *newtail,
2575  char **pnewpath)
2576 {
2577 char *srcpath, *newpath, *dir, *srctail;
2578 char newtemp[256];
2579 l_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 
2670 l_int32
2671 lept_cp(const char *srcfile,
2672  const char *newdir,
2673  const char *newtail,
2674  char **pnewpath)
2675 {
2676 char *srcpath, *newpath, *dir, *srctail;
2677 char newtemp[256];
2678 l_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 
2751 void
2752 callSystemDebug(const char *cmd)
2753 {
2754 l_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  *--------------------------------------------------------------------*/
2823 l_ok
2824 splitPathAtDirectory(const char *pathname,
2825  char **pdir,
2826  char **ptail)
2827 {
2828 char *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 
2893 l_ok
2894 splitPathAtExtension(const char *pathname,
2895  char **pbasename,
2896  char **pextension)
2897 {
2898 char *tail, *dir, *lastdot;
2899 char 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 
2972 char *
2973 pathJoin(const char *dir,
2974  const char *fname)
2975 {
2976 const char *slash = "/";
2977 char *str, *dest;
2978 l_int32 i, n1, n2, emptydir;
2979 size_t size;
2980 SARRAY *sa1, *sa2;
2981 L_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 
3051 char *
3052 appendSubdirs(const char *basedir,
3053  const char *subdirs)
3054 {
3055 char *newdir;
3056 size_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  *--------------------------------------------------------------------*/
3107 l_ok
3109  l_int32 type)
3110 {
3111 l_int32 i;
3112 size_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 
3172 char *
3173 genPathname(const char *dir,
3174  const char *fname)
3175 {
3176 l_int32 is_win32 = FALSE;
3177 char *cdir, *pathout;
3178 l_int32 dirlen, namelen;
3179 size_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 
3281 l_ok
3282 makeTempDirname(char *result,
3283  size_t nbytes,
3284  const char *subdir)
3285 {
3286 char *dir, *path;
3287 l_int32 ret = 0;
3288 size_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 
3346 l_ok
3348  size_t nbytes,
3349  l_int32 flag)
3350 {
3351 char lastchar;
3352 size_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 
3396 char *
3398 {
3399 char 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 
3452 l_int32
3453 extractNumberFromFilename(const char *fname,
3454  l_int32 numpre,
3455  l_int32 numpost)
3456 {
3457 char *tail, *basename;
3458 l_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_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_uint8 * l_binaryReadSelectStream(FILE *fp, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelectStream()
Definition: utils2.c:1514
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1611
l_int32 lept_mv(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_mv()
Definition: utils2.c:2572
l_int32 n
Definition: bbuffer.h:53
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218
l_ok l_byteaAppendString(L_BYTEA *ba, const char *str)
l_byteaAppendString()
Definition: bytearray.c:401
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 l_dnaGetCount(L_DNA *da)
l_dnaGetCount()
Definition: dnabasic.c:631
L_BBUFFER * bbufferCreate(const l_uint8 *indata, l_int32 nalloc)
bbufferCreate()
Definition: bbuffer.c:130
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2894
l_int32 stringLength(const char *src, size_t size)
stringLength()
Definition: utils2.c:381
l_ok stringCheckForChars(const char *src, const char *chars, l_int32 *pfound)
stringCheckForChars()
Definition: utils2.c:787
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition: utils2.c:3173
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition: utils2.c:1173
L_BYTEA * l_byteaCreate(size_t nbytes)
l_byteaCreate()
Definition: bytearray.c:97
char * l_makeTempFilename(void)
l_makeTempFilename()
Definition: utils2.c:3397
void l_dnaDestroy(L_DNA **pda)
l_dnaDestroy()
Definition: dnabasic.c:332
char * stringReplaceSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *ploc, l_int32 *pfound)
stringReplaceSubstr()
Definition: utils2.c:935
l_ok fileCopy(const char *srcfile, const char *newfile)
fileCopy()
Definition: utils2.c:1747
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
char * appendSubdirs(const char *basedir, const char *subdirs)
appendSubdirs()
Definition: utils2.c:3052
l_uint8 * l_binaryReadSelect(const char *filename, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelect()
Definition: utils2.c:1469
void * lept_calloc(size_t nmemb, size_t size)
lept_calloc()
Definition: utils2.c:2169
Definition: pix.h:710
l_ok l_dnaGetIValue(L_DNA *da, l_int32 index, l_int32 *pival)
l_dnaGetIValue()
Definition: dnabasic.c:727
l_ok fileConcatenate(const char *srcfile, const char *destfile)
fileConcatenate()
Definition: utils2.c:1777
char * stringCopySegment(const char *src, l_int32 start, l_int32 nbytes)
stringCopySegment()
Definition: utils2.c:305
char * stringRemoveChars(const char *src, const char *remchars)
stringRemoveChars()
Definition: utils2.c:822
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
Definition: array.h:94
char * sarrayToStringRange(SARRAY *sa, l_int32 first, l_int32 nstrings, l_int32 addnlflag)
sarrayToStringRange()
Definition: sarray1.c:820
SARRAY * getFilenamesInDirectory(const char *dirname)
getFilenamesInDirectory()
Definition: sarray1.c:1990
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
l_int32 lept_cp(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_cp()
Definition: utils2.c:2671
l_int32 lept_rm_match(const char *subdir, const char *substr)
lept_rm_match()
Definition: utils2.c:2427
l_ok l_dnaAddNumber(L_DNA *da, l_float64 val)
l_dnaAddNumber()
Definition: dnabasic.c:448
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition: utils2.c:3347
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
Definition: array.h:126
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition: utils2.c:423
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352
l_ok stringSplitOnToken(char *cstr, const char *seps, char **phead, char **ptail)
stringSplitOnToken()
Definition: utils2.c:743
NUMA * numaGetUniformBinSizes(l_int32 ntotal, l_int32 nbins)
numaGetUniformBinSizes()
Definition: numafunc2.c:1945
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
Definition: array.h:70
l_int32 nalloc
Definition: bbuffer.h:52
l_uint8 * array
Definition: bbuffer.h:55
l_ok stringJoinIP(char **psrc1, const char *src2)
stringJoinIP()
Definition: utils2.c:573
void lept_free(void *ptr)
lept_free()
Definition: utils2.c:2190
l_ok fileAppendString(const char *filename, const char *str)
fileAppendString()
Definition: utils2.c:1805
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition: utils2.c:1635
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:703
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1302
char * stringReplaceEachSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *pcount)
stringReplaceEachSubstr()
Definition: utils2.c:878
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:345
void lept_direxists(const char *dir, l_int32 *pexists)
lept_direxists()
Definition: utils2.c:2369
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:283
SARRAY * getSortedPathnamesInDirectory(const char *dirname, const char *substr, l_int32 first, l_int32 nfiles)
getSortedPathnamesInDirectory()
Definition: sarray1.c:1848
l_int32 extractNumberFromFilename(const char *fname, l_int32 numpre, l_int32 numpost)
extractNumberFromFilename()
Definition: utils2.c:3453
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2824
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
void bbufferDestroy(L_BBUFFER **pbb)
bbufferDestroy()
Definition: bbuffer.c:172
l_uint8 * l_binaryCopy(const l_uint8 *datas, size_t size)
l_binaryCopy()
Definition: utils2.c:1675
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
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
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:643
FILE * lept_fopen(const char *filename, const char *mode)
lept_fopen()
Definition: utils2.c:2113
L_DNA * stringFindEachSubstr(const char *src, const char *sub)
stringFindEachSubstr()
Definition: utils2.c:996
l_ok lept_fclose(FILE *fp)
lept_fclose()
Definition: utils2.c:2143
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2973
L_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:180
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition: utils2.c:518
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition: utils2.c:3282
l_ok convertSepCharsInPath(char *path, l_int32 type)
convertSepCharsInPath()
Definition: utils2.c:3108
l_ok bbufferExtendArray(L_BBUFFER *bb, l_int32 nbytes)
bbufferExtendArray()
Definition: bbuffer.c:363
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition: utils2.c:2752
char * strtokSafe(char *cstr, const char *seps, char **psaveptr)
strtokSafe()
Definition: utils2.c:649
void l_byteaDestroy(L_BYTEA **pba)
l_byteaDestroy()
Definition: bytearray.c:250
l_ok stringCopy(char *dest, const char *src, l_int32 n)
stringCopy()
Definition: utils2.c:263
l_int32 stringFindSubstr(const char *src, const char *sub, l_int32 *ploc)
stringFindSubstr()
Definition: utils2.c:1027
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
char * stringReverse(const char *src)
stringReverse()
Definition: utils2.c:597
l_int32 lept_rm(const char *subdir, const char *tail)
lept_rm()
Definition: utils2.c:2477
char * stringConcatNew(const char *first,...)
stringConcatNew()
Definition: utils2.c:471
l_uint8 * l_byteaCopyData(L_BYTEA *ba, size_t *psize)
l_byteaCopyData()
Definition: bytearray.c:336
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_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2517
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:362
Definition: array.h:136