Leptonica  1.77.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 
175 #ifdef HAVE_CONFIG_H
176 #include "config_auto.h"
177 #endif /* HAVE_CONFIG_H */
178 
179 #ifdef _MSC_VER
180 #include <process.h>
181 #include <direct.h>
182 #else
183 #include <unistd.h>
184 #endif /* _MSC_VER */
185 
186 #ifdef _WIN32
187 #include <windows.h>
188 #include <fcntl.h> /* _O_CREAT, ... */
189 #include <io.h> /* _open */
190 #include <sys/stat.h> /* _S_IREAD, _S_IWRITE */
191 #else
192 #include <sys/stat.h> /* for stat, mkdir(2) */
193 #include <sys/types.h>
194 #endif
195 
196 #include <string.h>
197 #include <stddef.h>
198 #include "allheaders.h"
199 
200 /* This is only used to test "/tmp" --> TMPDIR rewriting on Windows,
201  * by emulating it in unix. It should never be on in production. */
202 #define DEBUG_REWRITE 0
203 
204 
205 /*--------------------------------------------------------------------*
206  * Safe string operations *
207  *--------------------------------------------------------------------*/
214 char *
215 stringNew(const char *src)
216 {
217 l_int32 len;
218 char *dest;
219 
220  PROCNAME("stringNew");
221 
222  if (!src) {
223  L_WARNING("src not defined\n", procName);
224  return NULL;
225  }
226 
227  len = strlen(src);
228  if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
229  return (char *)ERROR_PTR("dest not made", procName, NULL);
230 
231  stringCopy(dest, src, len);
232  return dest;
233 }
234 
235 
254 l_ok
255 stringCopy(char *dest,
256  const char *src,
257  l_int32 n)
258 {
259 l_int32 i;
260 
261  PROCNAME("stringCopy");
262 
263  if (!dest)
264  return ERROR_INT("dest not defined", procName, 1);
265  if (!src || n < 1)
266  return 0;
267 
268  /* Implementation of strncpy that valgrind doesn't complain about */
269  for (i = 0; i < n && src[i] != '\0'; i++)
270  dest[i] = src[i];
271  for (; i < n; i++)
272  dest[i] = '\0';
273  return 0;
274 }
275 
276 
296 char *
297 stringCopySegment(const char *src,
298  l_int32 start,
299  l_int32 nbytes)
300 {
301 char *dest;
302 l_int32 len;
303 
304  PROCNAME("stringCopySegment");
305 
306  if (!src)
307  return (char *)ERROR_PTR("src not defined", procName, NULL);
308  len = strlen(src);
309  if (start < 0 || start > len - 1)
310  return (char *)ERROR_PTR("invalid start", procName, NULL);
311  if (nbytes <= 0) /* copy to the end */
312  nbytes = len - start;
313  if (start + nbytes > len) /* truncate to the end */
314  nbytes = len - start;
315  if ((dest = (char *)LEPT_CALLOC(nbytes + 1, sizeof(char))) == NULL)
316  return (char *)ERROR_PTR("dest not made", procName, NULL);
317  stringCopy(dest, src + start, nbytes);
318  return dest;
319 }
320 
321 
336 l_ok
337 stringReplace(char **pdest,
338  const char *src)
339 {
340  PROCNAME("stringReplace");
341 
342  if (!pdest)
343  return ERROR_INT("pdest not defined", procName, 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  PROCNAME("stringLength");
379 
380  if (!src)
381  return ERROR_INT("src not defined", procName, 0);
382  if (size < 1)
383  return 0;
384 
385  for (i = 0; i < size; i++) {
386  if (src[i] == '\0')
387  return i;
388  }
389  return size; /* didn't find a NUL byte */
390 }
391 
392 
413 l_int32
414 stringCat(char *dest,
415  size_t size,
416  const char *src)
417 {
418 l_int32 i, n;
419 l_int32 lendest, lensrc;
420 
421  PROCNAME("stringCat");
422 
423  if (!dest)
424  return ERROR_INT("dest not defined", procName, -1);
425  if (size < 1)
426  return ERROR_INT("size < 1; too small", procName, -1);
427  if (!src)
428  return 0;
429 
430  lendest = stringLength(dest, size);
431  if (lendest == size)
432  return ERROR_INT("no terminating nul byte", procName, -1);
433  lensrc = stringLength(src, size);
434  if (lensrc == 0)
435  return 0;
436  n = (lendest + lensrc > size - 1 ? size - lendest - 1 : lensrc);
437  if (n < 1)
438  return ERROR_INT("dest too small for append", procName, -1);
439 
440  for (i = 0; i < n; i++)
441  dest[lendest + i] = src[i];
442  dest[lendest + n] = '\0';
443  return n;
444 }
445 
446 
461 char *
462 stringConcatNew(const char *first, ...)
463 {
464 size_t len;
465 char *result, *ptr;
466 const char *arg;
467 va_list args;
468 
469  if (!first) return NULL;
470 
471  /* Find the length of the output string */
472  va_start(args, first);
473  len = strlen(first);
474  while ((arg = va_arg(args, const char *)) != NULL)
475  len += strlen(arg);
476  va_end(args);
477  result = (char *)LEPT_CALLOC(len + 1, sizeof(char));
478 
479  /* Concatenate the args */
480  va_start(args, first);
481  ptr = result;
482  arg = first;
483  while (*arg)
484  *ptr++ = *arg++;
485  while ((arg = va_arg(args, const char *)) != NULL) {
486  while (*arg)
487  *ptr++ = *arg++;
488  }
489  va_end(args);
490  return result;
491 }
492 
493 
508 char *
509 stringJoin(const char *src1,
510  const char *src2)
511 {
512 char *dest;
513 l_int32 srclen1, srclen2, destlen;
514 
515  PROCNAME("stringJoin");
516 
517  srclen1 = (src1) ? strlen(src1) : 0;
518  srclen2 = (src2) ? strlen(src2) : 0;
519  destlen = srclen1 + srclen2 + 3;
520 
521  if ((dest = (char *)LEPT_CALLOC(destlen, sizeof(char))) == NULL)
522  return (char *)ERROR_PTR("calloc fail for dest", procName, NULL);
523 
524  if (src1)
525  stringCopy(dest, src1, srclen1);
526  if (src2)
527  strncat(dest, src2, srclen2);
528  return dest;
529 }
530 
531 
563 l_ok
564 stringJoinIP(char **psrc1,
565  const char *src2)
566 {
567 char *tmpstr;
568 
569  PROCNAME("stringJoinIP");
570 
571  if (!psrc1)
572  return ERROR_INT("&src1 not defined", procName, 1);
573 
574  tmpstr = stringJoin(*psrc1, src2);
575  LEPT_FREE(*psrc1);
576  *psrc1 = tmpstr;
577  return 0;
578 }
579 
580 
587 char *
588 stringReverse(const char *src)
589 {
590 char *dest;
591 l_int32 i, len;
592 
593  PROCNAME("stringReverse");
594 
595  if (!src)
596  return (char *)ERROR_PTR("src not defined", procName, NULL);
597  len = strlen(src);
598  if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
599  return (char *)ERROR_PTR("calloc fail for dest", procName, NULL);
600  for (i = 0; i < len; i++)
601  dest[i] = src[len - 1 - i];
602 
603  return dest;
604 }
605 
606 
639 char *
640 strtokSafe(char *cstr,
641  const char *seps,
642  char **psaveptr)
643 {
644 char nextc;
645 char *start, *substr;
646 l_int32 istart, i, j, nchars;
647 
648  PROCNAME("strtokSafe");
649 
650  if (!seps)
651  return (char *)ERROR_PTR("seps not defined", procName, NULL);
652  if (!psaveptr)
653  return (char *)ERROR_PTR("&saveptr not defined", procName, NULL);
654 
655  if (!cstr) {
656  start = *psaveptr;
657  } else {
658  start = cstr;
659  *psaveptr = NULL;
660  }
661  if (!start) /* nothing to do */
662  return NULL;
663 
664  /* First time, scan for the first non-sep character */
665  istart = 0;
666  if (cstr) {
667  for (istart = 0;; istart++) {
668  if ((nextc = start[istart]) == '\0') {
669  *psaveptr = NULL; /* in case caller doesn't check ret value */
670  return NULL;
671  }
672  if (!strchr(seps, nextc))
673  break;
674  }
675  }
676 
677  /* Scan through, looking for a sep character; if none is
678  * found, 'i' will be at the end of the string. */
679  for (i = istart;; i++) {
680  if ((nextc = start[i]) == '\0')
681  break;
682  if (strchr(seps, nextc))
683  break;
684  }
685 
686  /* Save the substring */
687  nchars = i - istart;
688  substr = (char *)LEPT_CALLOC(nchars + 1, sizeof(char));
689  stringCopy(substr, start + istart, nchars);
690 
691  /* Look for the next non-sep character.
692  * If this is the last substring, return a null saveptr. */
693  for (j = i;; j++) {
694  if ((nextc = start[j]) == '\0') {
695  *psaveptr = NULL; /* no more non-sep characters */
696  break;
697  }
698  if (!strchr(seps, nextc)) {
699  *psaveptr = start + j; /* start here on next call */
700  break;
701  }
702  }
703 
704  return substr;
705 }
706 
707 
733 l_ok
735  const char *seps,
736  char **phead,
737  char **ptail)
738 {
739 char *saveptr;
740 
741  PROCNAME("stringSplitOnToken");
742 
743  if (!phead)
744  return ERROR_INT("&head not defined", procName, 1);
745  if (!ptail)
746  return ERROR_INT("&tail not defined", procName, 1);
747  *phead = *ptail = NULL;
748  if (!cstr)
749  return ERROR_INT("cstr not defined", procName, 1);
750  if (!seps)
751  return ERROR_INT("seps not defined", procName, 1);
752 
753  *phead = strtokSafe(cstr, seps, &saveptr);
754  if (saveptr)
755  *ptail = stringNew(saveptr);
756  return 0;
757 }
758 
759 
760 /*--------------------------------------------------------------------*
761  * Find and replace procs *
762  *--------------------------------------------------------------------*/
777 l_ok
778 stringCheckForChars(const char *src,
779  const char *chars,
780  l_int32 *pfound)
781 {
782 char ch;
783 l_int32 i, n;
784 
785  PROCNAME("stringCheckForChars");
786 
787  if (!pfound)
788  return ERROR_INT("&found not defined", procName, 1);
789  *pfound = FALSE;
790  if (!src || !chars)
791  return ERROR_INT("src and chars not both defined", procName, 1);
792 
793  n = strlen(src);
794  for (i = 0; i < n; i++) {
795  ch = src[i];
796  if (strchr(chars, ch)) {
797  *pfound = TRUE;
798  break;
799  }
800  }
801  return 0;
802 }
803 
804 
812 char *
813 stringRemoveChars(const char *src,
814  const char *remchars)
815 {
816 char ch;
817 char *dest;
818 l_int32 nsrc, i, k;
819 
820  PROCNAME("stringRemoveChars");
821 
822  if (!src)
823  return (char *)ERROR_PTR("src not defined", procName, NULL);
824  if (!remchars)
825  return stringNew(src);
826 
827  if ((dest = (char *)LEPT_CALLOC(strlen(src) + 1, sizeof(char))) == NULL)
828  return (char *)ERROR_PTR("dest not made", procName, NULL);
829  nsrc = strlen(src);
830  for (i = 0, k = 0; i < nsrc; i++) {
831  ch = src[i];
832  if (!strchr(remchars, ch))
833  dest[k++] = ch;
834  }
835 
836  return dest;
837 }
838 
839 
857 l_int32
858 stringFindSubstr(const char *src,
859  const char *sub,
860  l_int32 *ploc)
861 {
862 const char *ptr;
863 
864  PROCNAME("stringFindSubstr");
865 
866  if (!src)
867  return ERROR_INT("src not defined", procName, 0);
868  if (!sub)
869  return ERROR_INT("sub not defined", procName, 0);
870  if (ploc) *ploc = -1;
871  if (strlen(sub) == 0)
872  return ERROR_INT("substring length 0", procName, 0);
873  if (strlen(src) == 0)
874  return 0;
875 
876  if ((ptr = strstr(src, sub)) == NULL) /* not found */
877  return 0;
878 
879  if (ploc)
880  *ploc = ptr - src;
881  return 1;
882 }
883 
884 
909 char *
910 stringReplaceSubstr(const char *src,
911  const char *sub1,
912  const char *sub2,
913  l_int32 *pfound,
914  l_int32 *ploc)
915 {
916 const char *ptr;
917 char *dest;
918 l_int32 nsrc, nsub1, nsub2, len, npre, loc;
919 
920  PROCNAME("stringReplaceSubstr");
921 
922  if (!src)
923  return (char *)ERROR_PTR("src not defined", procName, NULL);
924  if (!sub1)
925  return (char *)ERROR_PTR("sub1 not defined", procName, NULL);
926  if (!sub2)
927  return (char *)ERROR_PTR("sub2 not defined", procName, NULL);
928 
929  if (pfound)
930  *pfound = 0;
931  if (ploc)
932  loc = *ploc;
933  else
934  loc = 0;
935  if ((ptr = strstr(src + loc, sub1)) == NULL) {
936  return NULL;
937  }
938 
939  if (pfound)
940  *pfound = 1;
941  nsrc = strlen(src);
942  nsub1 = strlen(sub1);
943  nsub2 = strlen(sub2);
944  len = nsrc + nsub2 - nsub1;
945  if ((dest = (char *)LEPT_CALLOC(len + 1, sizeof(char))) == NULL)
946  return (char *)ERROR_PTR("dest not made", procName, NULL);
947  npre = ptr - src;
948  memcpy(dest, src, npre);
949  strcpy(dest + npre, sub2);
950  strcpy(dest + npre + nsub2, ptr + nsub1);
951  if (ploc)
952  *ploc = npre + nsub2;
953 
954  return dest;
955 }
956 
957 
976 char *
977 stringReplaceEachSubstr(const char *src,
978  const char *sub1,
979  const char *sub2,
980  l_int32 *pcount)
981 {
982 char *currstr, *newstr;
983 l_int32 loc;
984 
985  PROCNAME("stringReplaceEachSubstr");
986 
987  if (pcount) *pcount = 0;
988  if (!src)
989  return (char *)ERROR_PTR("src not defined", procName, NULL);
990  if (!sub1)
991  return (char *)ERROR_PTR("sub1 not defined", procName, NULL);
992  if (!sub2)
993  return (char *)ERROR_PTR("sub2 not defined", procName, NULL);
994 
995  loc = 0;
996  if ((newstr = stringReplaceSubstr(src, sub1, sub2, NULL, &loc)) == NULL)
997  return NULL;
998 
999  if (pcount)
1000  (*pcount)++;
1001  while (1) {
1002  currstr = newstr;
1003  newstr = stringReplaceSubstr(currstr, sub1, sub2, NULL, &loc);
1004  if (!newstr)
1005  return currstr;
1006  LEPT_FREE(currstr);
1007  if (pcount)
1008  (*pcount)++;
1009  }
1010 }
1011 
1012 
1031 L_DNA *
1032 arrayFindEachSequence(const l_uint8 *data,
1033  size_t datalen,
1034  const l_uint8 *sequence,
1035  size_t seqlen)
1036 {
1037 l_int32 start, offset, realoffset, found;
1038 L_DNA *da;
1039 
1040  PROCNAME("arrayFindEachSequence");
1041 
1042  if (!data || !sequence)
1043  return (L_DNA *)ERROR_PTR("data & sequence not both defined",
1044  procName, NULL);
1045 
1046  da = l_dnaCreate(0);
1047  start = 0;
1048  while (1) {
1049  arrayFindSequence(data + start, datalen - start, sequence, seqlen,
1050  &offset, &found);
1051  if (found == FALSE)
1052  break;
1053 
1054  realoffset = start + offset;
1055  l_dnaAddNumber(da, realoffset);
1056  start = realoffset + seqlen;
1057  if (start >= datalen)
1058  break;
1059  }
1060 
1061  if (l_dnaGetCount(da) == 0)
1062  l_dnaDestroy(&da);
1063  return da;
1064 }
1065 
1066 
1091 l_ok
1092 arrayFindSequence(const l_uint8 *data,
1093  size_t datalen,
1094  const l_uint8 *sequence,
1095  size_t seqlen,
1096  l_int32 *poffset,
1097  l_int32 *pfound)
1098 {
1099 l_int32 i, j, found, lastpos;
1100 
1101  PROCNAME("arrayFindSequence");
1102 
1103  if (poffset) *poffset = 0;
1104  if (pfound) *pfound = FALSE;
1105  if (!data || !sequence)
1106  return ERROR_INT("data & sequence not both defined", procName, 1);
1107  if (!poffset || !pfound)
1108  return ERROR_INT("&offset and &found not defined", procName, 1);
1109 
1110  lastpos = datalen - seqlen + 1;
1111  found = FALSE;
1112  for (i = 0; i < lastpos; i++) {
1113  for (j = 0; j < seqlen; j++) {
1114  if (data[i + j] != sequence[j])
1115  break;
1116  if (j == seqlen - 1)
1117  found = TRUE;
1118  }
1119  if (found == TRUE)
1120  break;
1121  }
1122 
1123  if (found == TRUE) {
1124  *poffset = i;
1125  *pfound = TRUE;
1126  }
1127  return 0;
1128 }
1129 
1130 
1131 /*--------------------------------------------------------------------*
1132  * Safe realloc *
1133  *--------------------------------------------------------------------*/
1160 void *
1161 reallocNew(void **pindata,
1162  l_int32 oldsize,
1163  l_int32 newsize)
1164 {
1165 l_int32 minsize;
1166 void *indata;
1167 void *newdata;
1168 
1169  PROCNAME("reallocNew");
1170 
1171  if (!pindata)
1172  return ERROR_PTR("input data not defined", procName, NULL);
1173  indata = *pindata;
1174 
1175  if (newsize <= 0) { /* nonstandard usage */
1176  if (indata) {
1177  LEPT_FREE(indata);
1178  *pindata = NULL;
1179  }
1180  return NULL;
1181  }
1182 
1183  if (!indata) { /* nonstandard usage */
1184  if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1185  return ERROR_PTR("newdata not made", procName, NULL);
1186  return newdata;
1187  }
1188 
1189  /* Standard usage */
1190  if ((newdata = (void *)LEPT_CALLOC(1, newsize)) == NULL)
1191  return ERROR_PTR("newdata not made", procName, NULL);
1192  minsize = L_MIN(oldsize, newsize);
1193  memcpy(newdata, indata, minsize);
1194  LEPT_FREE(indata);
1195  *pindata = NULL;
1196 
1197  return newdata;
1198 }
1199 
1200 
1201 /*--------------------------------------------------------------------*
1202  * Read and write between file and memory *
1203  *--------------------------------------------------------------------*/
1211 l_uint8 *
1212 l_binaryRead(const char *filename,
1213  size_t *pnbytes)
1214 {
1215 l_uint8 *data;
1216 FILE *fp;
1217 
1218  PROCNAME("l_binaryRead");
1219 
1220  if (!pnbytes)
1221  return (l_uint8 *)ERROR_PTR("pnbytes not defined", procName, NULL);
1222  *pnbytes = 0;
1223  if (!filename)
1224  return (l_uint8 *)ERROR_PTR("filename not defined", procName, NULL);
1225 
1226  if ((fp = fopenReadStream(filename)) == NULL)
1227  return (l_uint8 *)ERROR_PTR("file stream not opened", procName, NULL);
1228  data = l_binaryReadStream(fp, pnbytes);
1229  fclose(fp);
1230  return data;
1231 }
1232 
1233 
1261 l_uint8 *
1263  size_t *pnbytes)
1264 {
1265 l_uint8 *data;
1266 l_int32 seekable, navail, nadd, nread;
1267 L_BBUFFER *bb;
1268 
1269  PROCNAME("l_binaryReadStream");
1270 
1271  if (!pnbytes)
1272  return (l_uint8 *)ERROR_PTR("&nbytes not defined", procName, NULL);
1273  *pnbytes = 0;
1274  if (!fp)
1275  return (l_uint8 *)ERROR_PTR("fp not defined", procName, NULL);
1276 
1277  /* Test if the stream is seekable, by attempting to seek to
1278  * the start of data. This is a no-op. If it is seekable, use
1279  * l_binaryReadSelectStream() to determine the size of the
1280  * data to be read in advance. */
1281  seekable = (ftell(fp) == 0) ? 1 : 0;
1282  if (seekable)
1283  return l_binaryReadSelectStream(fp, 0, 0, pnbytes);
1284 
1285  /* If it is not seekable, use the bbuffer to realloc memory
1286  * as needed during reading. */
1287  bb = bbufferCreate(NULL, 4096);
1288  while (1) {
1289  navail = bb->nalloc - bb->n;
1290  if (navail < 4096) {
1291  nadd = L_MAX(bb->nalloc, 4096);
1292  bbufferExtendArray(bb, nadd);
1293  }
1294  nread = fread((void *)(bb->array + bb->n), 1, 4096, fp);
1295  bb->n += nread;
1296  if (nread != 4096) break;
1297  }
1298 
1299  /* Copy the data to a new array sized for the data, because
1300  * the bbuffer array can be nearly twice the size we need. */
1301  if ((data = (l_uint8 *)LEPT_CALLOC(bb->n + 1, sizeof(l_uint8))) != NULL) {
1302  memcpy(data, bb->array, bb->n);
1303  *pnbytes = bb->n;
1304  } else {
1305  L_ERROR("calloc fail for data\n", procName);
1306  }
1307 
1308  bbufferDestroy(&bb);
1309  return data;
1310 }
1311 
1312 
1328 l_uint8 *
1329 l_binaryReadSelect(const char *filename,
1330  size_t start,
1331  size_t nbytes,
1332  size_t *pnread)
1333 {
1334 l_uint8 *data;
1335 FILE *fp;
1336 
1337  PROCNAME("l_binaryReadSelect");
1338 
1339  if (!pnread)
1340  return (l_uint8 *)ERROR_PTR("pnread not defined", procName, NULL);
1341  *pnread = 0;
1342  if (!filename)
1343  return (l_uint8 *)ERROR_PTR("filename not defined", procName, NULL);
1344 
1345  if ((fp = fopenReadStream(filename)) == NULL)
1346  return (l_uint8 *)ERROR_PTR("file stream not opened", procName, NULL);
1347  data = l_binaryReadSelectStream(fp, start, nbytes, pnread);
1348  fclose(fp);
1349  return data;
1350 }
1351 
1352 
1373 l_uint8 *
1375  size_t start,
1376  size_t nbytes,
1377  size_t *pnread)
1378 {
1379 l_uint8 *data;
1380 size_t bytesleft, bytestoread, nread, filebytes;
1381 
1382  PROCNAME("l_binaryReadSelectStream");
1383 
1384  if (!pnread)
1385  return (l_uint8 *)ERROR_PTR("&nread not defined", procName, NULL);
1386  *pnread = 0;
1387  if (!fp)
1388  return (l_uint8 *)ERROR_PTR("stream not defined", procName, NULL);
1389 
1390  /* Verify and adjust the parameters if necessary */
1391  fseek(fp, 0, SEEK_END); /* EOF */
1392  filebytes = ftell(fp);
1393  fseek(fp, 0, SEEK_SET);
1394  if (start > filebytes) {
1395  L_ERROR("start = %lu but filebytes = %lu\n", procName,
1396  (unsigned long)start, (unsigned long)filebytes);
1397  return NULL;
1398  }
1399  if (filebytes == 0) /* start == 0; nothing to read; return null byte */
1400  return (l_uint8 *)LEPT_CALLOC(1, 1);
1401  bytesleft = filebytes - start; /* greater than 0 */
1402  if (nbytes == 0) nbytes = bytesleft;
1403  bytestoread = (bytesleft >= nbytes) ? nbytes : bytesleft;
1404 
1405  /* Read the data */
1406  if ((data = (l_uint8 *)LEPT_CALLOC(1, bytestoread + 1)) == NULL)
1407  return (l_uint8 *)ERROR_PTR("calloc fail for data", procName, NULL);
1408  fseek(fp, start, SEEK_SET);
1409  nread = fread(data, 1, bytestoread, fp);
1410  if (nbytes != nread)
1411  L_INFO("%lu bytes requested; %lu bytes read\n", procName,
1412  (unsigned long)nbytes, (unsigned long)nread);
1413  *pnread = nread;
1414  fseek(fp, 0, SEEK_SET);
1415  return data;
1416 }
1417 
1418 
1428 l_ok
1429 l_binaryWrite(const char *filename,
1430  const char *operation,
1431  const void *data,
1432  size_t nbytes)
1433 {
1434 char actualOperation[20];
1435 FILE *fp;
1436 
1437  PROCNAME("l_binaryWrite");
1438 
1439  if (!filename)
1440  return ERROR_INT("filename not defined", procName, 1);
1441  if (!operation)
1442  return ERROR_INT("operation not defined", procName, 1);
1443  if (!data)
1444  return ERROR_INT("data not defined", procName, 1);
1445  if (nbytes <= 0)
1446  return ERROR_INT("nbytes must be > 0", procName, 1);
1447 
1448  if (strcmp(operation, "w") && strcmp(operation, "a"))
1449  return ERROR_INT("operation not one of {'w','a'}", procName, 1);
1450 
1451  /* The 'b' flag to fopen() is ignored for all POSIX
1452  * conforming systems. However, Windows needs the 'b' flag. */
1453  stringCopy(actualOperation, operation, 2);
1454  strncat(actualOperation, "b", 2);
1455 
1456  if ((fp = fopenWriteStream(filename, actualOperation)) == NULL)
1457  return ERROR_INT("stream not opened", procName, 1);
1458  fwrite(data, 1, nbytes, fp);
1459  fclose(fp);
1460  return 0;
1461 }
1462 
1463 
1470 size_t
1471 nbytesInFile(const char *filename)
1472 {
1473 size_t nbytes;
1474 FILE *fp;
1475 
1476  PROCNAME("nbytesInFile");
1477 
1478  if (!filename)
1479  return ERROR_INT("filename not defined", procName, 0);
1480  if ((fp = fopenReadStream(filename)) == NULL)
1481  return ERROR_INT("stream not opened", procName, 0);
1482  nbytes = fnbytesInFile(fp);
1483  fclose(fp);
1484  return nbytes;
1485 }
1486 
1487 
1494 size_t
1495 fnbytesInFile(FILE *fp)
1496 {
1497 l_int64 pos, nbytes;
1498 
1499  PROCNAME("fnbytesInFile");
1500 
1501  if (!fp)
1502  return ERROR_INT("stream not open", procName, 0);
1503 
1504  pos = ftell(fp); /* initial position */
1505  if (pos < 0)
1506  return ERROR_INT("seek position must be > 0", procName, 0);
1507  fseek(fp, 0, SEEK_END); /* EOF */
1508  nbytes = ftell(fp);
1509  fseek(fp, pos, SEEK_SET); /* back to initial position */
1510  return nbytes;
1511 }
1512 
1513 
1514 /*--------------------------------------------------------------------*
1515  * Copy in memory *
1516  *--------------------------------------------------------------------*/
1532 l_uint8 *
1533 l_binaryCopy(l_uint8 *datas,
1534  size_t size)
1535 {
1536 l_uint8 *datad;
1537 
1538  PROCNAME("l_binaryCopy");
1539 
1540  if (!datas)
1541  return (l_uint8 *)ERROR_PTR("datas not defined", procName, NULL);
1542 
1543  if ((datad = (l_uint8 *)LEPT_CALLOC(size + 4, sizeof(l_uint8))) == NULL)
1544  return (l_uint8 *)ERROR_PTR("datad not made", procName, NULL);
1545  memcpy(datad, datas, size);
1546  return datad;
1547 }
1548 
1549 
1550 /*--------------------------------------------------------------------*
1551  * File copy operations *
1552  *--------------------------------------------------------------------*/
1560 l_ok
1561 fileCopy(const char *srcfile,
1562  const char *newfile)
1563 {
1564 l_int32 ret;
1565 size_t nbytes;
1566 l_uint8 *data;
1567 
1568  PROCNAME("fileCopy");
1569 
1570  if (!srcfile)
1571  return ERROR_INT("srcfile not defined", procName, 1);
1572  if (!newfile)
1573  return ERROR_INT("newfile not defined", procName, 1);
1574 
1575  if ((data = l_binaryRead(srcfile, &nbytes)) == NULL)
1576  return ERROR_INT("data not returned", procName, 1);
1577  ret = l_binaryWrite(newfile, "w", data, nbytes);
1578  LEPT_FREE(data);
1579  return ret;
1580 }
1581 
1582 
1590 l_ok
1591 fileConcatenate(const char *srcfile,
1592  const char *destfile)
1593 {
1594 size_t nbytes;
1595 l_uint8 *data;
1596 
1597  PROCNAME("fileConcatenate");
1598 
1599  if (!srcfile)
1600  return ERROR_INT("srcfile not defined", procName, 1);
1601  if (!destfile)
1602  return ERROR_INT("destfile not defined", procName, 1);
1603 
1604  data = l_binaryRead(srcfile, &nbytes);
1605  l_binaryWrite(destfile, "a", data, nbytes);
1606  LEPT_FREE(data);
1607  return 0;
1608 }
1609 
1610 
1618 l_ok
1619 fileAppendString(const char *filename,
1620  const char *str)
1621 {
1622 FILE *fp;
1623 
1624  PROCNAME("fileAppendString");
1625 
1626  if (!filename)
1627  return ERROR_INT("filename not defined", procName, 1);
1628  if (!str)
1629  return ERROR_INT("str not defined", procName, 1);
1630 
1631  if ((fp = fopenWriteStream(filename, "a")) == NULL)
1632  return ERROR_INT("stream not opened", procName, 1);
1633  fprintf(fp, "%s", str);
1634  fclose(fp);
1635  return 0;
1636 }
1637 
1638 
1639 /*--------------------------------------------------------------------*
1640  * Multi-platform functions for opening file streams *
1641  *--------------------------------------------------------------------*/
1656 FILE *
1657 fopenReadStream(const char *filename)
1658 {
1659 char *fname, *tail;
1660 FILE *fp;
1661 
1662  PROCNAME("fopenReadStream");
1663 
1664  if (!filename)
1665  return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
1666 
1667  /* Try input filename */
1668  fname = genPathname(filename, NULL);
1669  fp = fopen(fname, "rb");
1670  LEPT_FREE(fname);
1671  if (fp) return fp;
1672 
1673  /* Else, strip directory and try locally */
1674  splitPathAtDirectory(filename, NULL, &tail);
1675  fp = fopen(tail, "rb");
1676  LEPT_FREE(tail);
1677 
1678  if (!fp)
1679  return (FILE *)ERROR_PTR("file not found", procName, NULL);
1680  return fp;
1681 }
1682 
1683 
1699 FILE *
1700 fopenWriteStream(const char *filename,
1701  const char *modestring)
1702 {
1703 char *fname;
1704 FILE *fp;
1705 
1706  PROCNAME("fopenWriteStream");
1707 
1708  if (!filename)
1709  return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
1710 
1711  fname = genPathname(filename, NULL);
1712  fp = fopen(fname, modestring);
1713  LEPT_FREE(fname);
1714  if (!fp)
1715  return (FILE *)ERROR_PTR("stream not opened", procName, NULL);
1716  return fp;
1717 }
1718 
1719 
1733 FILE *
1734 fopenReadFromMemory(const l_uint8 *data,
1735  size_t size)
1736 {
1737 FILE *fp;
1738 
1739  PROCNAME("fopenReadFromMemory");
1740 
1741  if (!data)
1742  return (FILE *)ERROR_PTR("data not defined", procName, NULL);
1743 
1744 #if HAVE_FMEMOPEN
1745  if ((fp = fmemopen((void *)data, size, "rb")) == NULL)
1746  return (FILE *)ERROR_PTR("stream not opened", procName, NULL);
1747 #else /* write to tmp file */
1748  L_INFO("work-around: writing to a temp file\n", procName);
1749  #ifdef _WIN32
1750  if ((fp = fopenWriteWinTempfile()) == NULL)
1751  return (FILE *)ERROR_PTR("tmpfile stream not opened", procName, NULL);
1752  #else
1753  if ((fp = tmpfile()) == NULL)
1754  return (FILE *)ERROR_PTR("tmpfile stream not opened", procName, NULL);
1755  #endif /* _WIN32 */
1756  fwrite(data, 1, size, fp);
1757  rewind(fp);
1758 #endif /* HAVE_FMEMOPEN */
1759 
1760  return fp;
1761 }
1762 
1763 
1764 /*--------------------------------------------------------------------*
1765  * Opening a windows tmpfile for writing *
1766  *--------------------------------------------------------------------*/
1779 FILE *
1781 {
1782 #ifdef _WIN32
1783 l_int32 handle;
1784 FILE *fp;
1785 char *filename;
1786 
1787  PROCNAME("fopenWriteWinTempfile");
1788 
1789  if ((filename = l_makeTempFilename()) == NULL) {
1790  L_ERROR("l_makeTempFilename failed, %s\n", procName, strerror(errno));
1791  return NULL;
1792  }
1793 
1794  handle = _open(filename, _O_CREAT | _O_RDWR | _O_SHORT_LIVED |
1795  _O_TEMPORARY | _O_BINARY, _S_IREAD | _S_IWRITE);
1796  lept_free(filename);
1797  if (handle == -1) {
1798  L_ERROR("_open failed, %s\n", procName, strerror(errno));
1799  return NULL;
1800  }
1801 
1802  if ((fp = _fdopen(handle, "r+b")) == NULL) {
1803  L_ERROR("_fdopen failed, %s\n", procName, strerror(errno));
1804  return NULL;
1805  }
1806 
1807  return fp;
1808 #else
1809  return NULL;
1810 #endif /* _WIN32 */
1811 }
1812 
1813 
1814 /*--------------------------------------------------------------------*
1815  * Multi-platform functions that avoid C-runtime boundary *
1816  * crossing for applications with Windows DLLs *
1817  *--------------------------------------------------------------------*/
1818 /*
1819  * Problems arise when pointers to streams and data are passed
1820  * between two Windows DLLs that have been generated with different
1821  * C runtimes. To avoid this, leptonica provides wrappers for
1822  * several C library calls.
1823  */
1837 FILE *
1838 lept_fopen(const char *filename,
1839  const char *mode)
1840 {
1841  PROCNAME("lept_fopen");
1842 
1843  if (!filename)
1844  return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
1845  if (!mode)
1846  return (FILE *)ERROR_PTR("mode not defined", procName, NULL);
1847 
1848  if (stringFindSubstr(mode, "r", NULL))
1849  return fopenReadStream(filename);
1850  else
1851  return fopenWriteStream(filename, mode);
1852 }
1853 
1854 
1867 l_ok
1868 lept_fclose(FILE *fp)
1869 {
1870  PROCNAME("lept_fclose");
1871 
1872  if (!fp)
1873  return ERROR_INT("stream not defined", procName, 1);
1874 
1875  return fclose(fp);
1876 }
1877 
1878 
1893 void *
1894 lept_calloc(size_t nmemb,
1895  size_t size)
1896 {
1897  if (nmemb <= 0 || size <= 0)
1898  return NULL;
1899  return LEPT_CALLOC(nmemb, size);
1900 }
1901 
1902 
1914 void
1915 lept_free(void *ptr)
1916 {
1917  if (!ptr) return;
1918  LEPT_FREE(ptr);
1919  return;
1920 }
1921 
1922 
1923 /*--------------------------------------------------------------------*
1924  * Multi-platform file system operations *
1925  * [ These only write to /tmp or its subdirectories ] *
1926  *--------------------------------------------------------------------*/
1943 l_int32
1944 lept_mkdir(const char *subdir)
1945 {
1946 char *dir, *tmpdir;
1947 l_int32 i, n;
1948 l_int32 ret = 0;
1949 SARRAY *sa;
1950 #ifdef _WIN32
1951 l_uint32 attributes;
1952 #endif /* _WIN32 */
1953 
1954  PROCNAME("lept_mkdir");
1955 
1956  if (!LeptDebugOK) {
1957  L_INFO("making named temp subdirectory %s is disabled\n",
1958  procName, subdir);
1959  return 0;
1960  }
1961 
1962  if (!subdir)
1963  return ERROR_INT("subdir not defined", procName, 1);
1964  if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
1965  return ERROR_INT("subdir not an actual subdirectory", procName, 1);
1966 
1967  sa = sarrayCreate(0);
1968  sarraySplitString(sa, subdir, "/");
1969  n = sarrayGetCount(sa);
1970  dir = genPathname("/tmp", NULL);
1971  /* Make sure the tmp directory exists */
1972 #ifndef _WIN32
1973  ret = mkdir(dir, 0777);
1974 #else
1975  attributes = GetFileAttributes(dir);
1976  if (attributes == INVALID_FILE_ATTRIBUTES)
1977  ret = (CreateDirectory(dir, NULL) ? 0 : 1);
1978 #endif
1979  /* Make all the subdirectories */
1980  for (i = 0; i < n; i++) {
1981  tmpdir = pathJoin(dir, sarrayGetString(sa, i, L_NOCOPY));
1982 #ifndef _WIN32
1983  ret += mkdir(tmpdir, 0777);
1984 #else
1985  if (CreateDirectory(tmpdir, NULL) == 0)
1986  ret += (GetLastError () != ERROR_ALREADY_EXISTS);
1987 #endif
1988  LEPT_FREE(dir);
1989  dir = tmpdir;
1990  }
1991  LEPT_FREE(dir);
1992  sarrayDestroy(&sa);
1993  if (ret > 0)
1994  L_ERROR("failure to create %d directories\n", procName, ret);
1995  return ret;
1996 }
1997 
1998 
2020 l_int32
2021 lept_rmdir(const char *subdir)
2022 {
2023 char *dir, *realdir, *fname, *fullname;
2024 l_int32 exists, ret, i, nfiles;
2025 SARRAY *sa;
2026 #ifdef _WIN32
2027 char *newpath;
2028 #endif /* _WIN32 */
2029 
2030  PROCNAME("lept_rmdir");
2031 
2032  if (!subdir)
2033  return ERROR_INT("subdir not defined", procName, 1);
2034  if ((strlen(subdir) == 0) || (subdir[0] == '.') || (subdir[0] == '/'))
2035  return ERROR_INT("subdir not an actual subdirectory", procName, 1);
2036 
2037  /* Find the temp subdirectory */
2038  dir = pathJoin("/tmp", subdir);
2039  if (!dir)
2040  return ERROR_INT("directory name not made", procName, 1);
2041  lept_direxists(dir, &exists);
2042  if (!exists) { /* fail silently */
2043  LEPT_FREE(dir);
2044  return 0;
2045  }
2046 
2047  /* List all the files in that directory */
2048  if ((sa = getFilenamesInDirectory(dir)) == NULL) {
2049  L_ERROR("directory %s does not exist!\n", procName, dir);
2050  LEPT_FREE(dir);
2051  return 1;
2052  }
2053  nfiles = sarrayGetCount(sa);
2054 
2055  for (i = 0; i < nfiles; i++) {
2056  fname = sarrayGetString(sa, i, L_NOCOPY);
2057  fullname = genPathname(dir, fname);
2058  remove(fullname);
2059  LEPT_FREE(fullname);
2060  }
2061 
2062 #ifndef _WIN32
2063  realdir = genPathname("/tmp", subdir);
2064  ret = rmdir(realdir);
2065  LEPT_FREE(realdir);
2066 #else
2067  newpath = genPathname(dir, NULL);
2068  ret = (RemoveDirectory(newpath) ? 0 : 1);
2069  LEPT_FREE(newpath);
2070 #endif /* !_WIN32 */
2071 
2072  sarrayDestroy(&sa);
2073  LEPT_FREE(dir);
2074  return ret;
2075 }
2076 
2077 
2094 void
2095 lept_direxists(const char *dir,
2096  l_int32 *pexists)
2097 {
2098 char *realdir;
2099 
2100  if (!pexists) return;
2101  *pexists = 0;
2102  if (!dir) return;
2103  if ((realdir = genPathname(dir, NULL)) == NULL)
2104  return;
2105 
2106 #ifndef _WIN32
2107  {
2108  struct stat s;
2109  l_int32 err = stat(realdir, &s);
2110  if (err != -1 && S_ISDIR(s.st_mode))
2111  *pexists = 1;
2112  }
2113 #else /* _WIN32 */
2114  l_uint32 attributes;
2115  attributes = GetFileAttributes(realdir);
2116  if (attributes != INVALID_FILE_ATTRIBUTES &&
2117  (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
2118  *pexists = 1;
2119  }
2120 #endif /* _WIN32 */
2121 
2122  LEPT_FREE(realdir);
2123  return;
2124 }
2125 
2126 
2152 l_int32
2153 lept_rm_match(const char *subdir,
2154  const char *substr)
2155 {
2156 char *path, *fname;
2157 char tempdir[256];
2158 l_int32 i, n, ret;
2159 SARRAY *sa;
2160 
2161  PROCNAME("lept_rm_match");
2162 
2163  makeTempDirname(tempdir, 256, subdir);
2164  if ((sa = getSortedPathnamesInDirectory(tempdir, substr, 0, 0)) == NULL)
2165  return ERROR_INT("sa not made", procName, -1);
2166  n = sarrayGetCount(sa);
2167  if (n == 0) {
2168  L_WARNING("no matching files found\n", procName);
2169  sarrayDestroy(&sa);
2170  return 0;
2171  }
2172 
2173  ret = 0;
2174  for (i = 0; i < n; i++) {
2175  fname = sarrayGetString(sa, i, L_NOCOPY);
2176  path = genPathname(fname, NULL);
2177  if (lept_rmfile(path) != 0) {
2178  L_ERROR("failed to remove %s\n", procName, path);
2179  ret++;
2180  }
2181  LEPT_FREE(path);
2182  }
2183  sarrayDestroy(&sa);
2184  return ret;
2185 }
2186 
2187 
2202 l_int32
2203 lept_rm(const char *subdir,
2204  const char *tail)
2205 {
2206 char *path;
2207 char newtemp[256];
2208 l_int32 ret;
2209 
2210  PROCNAME("lept_rm");
2211 
2212  if (!tail || strlen(tail) == 0)
2213  return ERROR_INT("tail undefined or empty", procName, 1);
2214 
2215  if (makeTempDirname(newtemp, 256, subdir))
2216  return ERROR_INT("temp dirname not made", procName, 1);
2217  path = genPathname(newtemp, tail);
2218  ret = lept_rmfile(path);
2219  LEPT_FREE(path);
2220  return ret;
2221 }
2222 
2223 
2242 l_int32
2243 lept_rmfile(const char *filepath)
2244 {
2245 l_int32 ret;
2246 
2247  PROCNAME("lept_rmfile");
2248 
2249  if (!filepath || strlen(filepath) == 0)
2250  return ERROR_INT("filepath undefined or empty", procName, 1);
2251 
2252 #ifndef _WIN32
2253  ret = remove(filepath);
2254 #else
2255  /* Set attributes to allow deletion of read-only files */
2256  SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL);
2257  ret = DeleteFile(filepath) ? 0 : 1;
2258 #endif /* !_WIN32 */
2259 
2260  return ret;
2261 }
2262 
2263 
2297 l_int32
2298 lept_mv(const char *srcfile,
2299  const char *newdir,
2300  const char *newtail,
2301  char **pnewpath)
2302 {
2303 char *srcpath, *newpath, *realpath, *dir, *srctail;
2304 char newtemp[256];
2305 l_int32 ret;
2306 
2307  PROCNAME("lept_mv");
2308 
2309  if (!srcfile)
2310  return ERROR_INT("srcfile not defined", procName, 1);
2311 
2312  /* Require output pathname to be in /tmp/ or a subdirectory */
2313  if (makeTempDirname(newtemp, 256, newdir) == 1)
2314  return ERROR_INT("newdir not NULL or a subdir of /tmp", procName, 1);
2315 
2316  /* Get canonical src pathname */
2317  splitPathAtDirectory(srcfile, &dir, &srctail);
2318 
2319 #ifndef _WIN32
2320  srcpath = pathJoin(dir, srctail);
2321  LEPT_FREE(dir);
2322 
2323  /* Generate output pathname */
2324  if (!newtail || newtail[0] == '\0')
2325  newpath = pathJoin(newtemp, srctail);
2326  else
2327  newpath = pathJoin(newtemp, newtail);
2328  LEPT_FREE(srctail);
2329 
2330  /* Overwrite any existing file at 'newpath' */
2331  ret = fileCopy(srcpath, newpath);
2332  if (!ret) {
2333  realpath = genPathname(srcpath, NULL);
2334  remove(realpath);
2335  LEPT_FREE(realpath);
2336  }
2337 #else
2338  srcpath = genPathname(dir, srctail);
2339  LEPT_FREE(dir);
2340 
2341  /* Generate output pathname */
2342  if (!newtail || newtail[0] == '\0')
2343  newpath = genPathname(newtemp, srctail);
2344  else
2345  newpath = genPathname(newtemp, newtail);
2346  LEPT_FREE(srctail);
2347 
2348  /* Overwrite any existing file at 'newpath' */
2349  ret = MoveFileEx(srcpath, newpath,
2350  MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) ? 0 : 1;
2351 #endif /* ! _WIN32 */
2352 
2353  LEPT_FREE(srcpath);
2354  if (pnewpath)
2355  *pnewpath = newpath;
2356  else
2357  LEPT_FREE(newpath);
2358  return ret;
2359 }
2360 
2361 
2396 l_int32
2397 lept_cp(const char *srcfile,
2398  const char *newdir,
2399  const char *newtail,
2400  char **pnewpath)
2401 {
2402 char *srcpath, *newpath, *dir, *srctail;
2403 char newtemp[256];
2404 l_int32 ret;
2405 
2406  PROCNAME("lept_cp");
2407 
2408  if (!srcfile)
2409  return ERROR_INT("srcfile not defined", procName, 1);
2410 
2411  /* Require output pathname to be in /tmp or a subdirectory */
2412  if (makeTempDirname(newtemp, 256, newdir) == 1)
2413  return ERROR_INT("newdir not NULL or a subdir of /tmp", procName, 1);
2414 
2415  /* Get canonical src pathname */
2416  splitPathAtDirectory(srcfile, &dir, &srctail);
2417 
2418 #ifndef _WIN32
2419  srcpath = pathJoin(dir, srctail);
2420  LEPT_FREE(dir);
2421 
2422  /* Generate output pathname */
2423  if (!newtail || newtail[0] == '\0')
2424  newpath = pathJoin(newtemp, srctail);
2425  else
2426  newpath = pathJoin(newtemp, newtail);
2427  LEPT_FREE(srctail);
2428 
2429  /* Overwrite any existing file at 'newpath' */
2430  ret = fileCopy(srcpath, newpath);
2431 #else
2432  srcpath = genPathname(dir, srctail);
2433  LEPT_FREE(dir);
2434 
2435  /* Generate output pathname */
2436  if (!newtail || newtail[0] == '\0')
2437  newpath = genPathname(newtemp, srctail);
2438  else
2439  newpath = genPathname(newtemp, newtail);
2440  LEPT_FREE(srctail);
2441 
2442  /* Overwrite any existing file at 'newpath' */
2443  ret = CopyFile(srcpath, newpath, FALSE) ? 0 : 1;
2444 #endif /* !_WIN32 */
2445 
2446  LEPT_FREE(srcpath);
2447  if (pnewpath)
2448  *pnewpath = newpath;
2449  else
2450  LEPT_FREE(newpath);
2451  return ret;
2452 }
2453 
2454 
2455 /*--------------------------------------------------------------------*
2456  * Special debug/test function for calling 'system' *
2457  *--------------------------------------------------------------------*/
2473 void
2474 callSystemDebug(const char *cmd)
2475 {
2476 l_int32 ret;
2477 
2478  PROCNAME("callSystemDebug");
2479 
2480  if (!cmd) {
2481  L_ERROR("cmd not defined\n", procName);
2482  return;
2483  }
2484  if (LeptDebugOK == FALSE) {
2485  L_INFO("'system' calls are disabled\n", procName);
2486  return;
2487  }
2488 
2489 #if defined (__APPLE__) /* iOS 11 does not support system() */
2490 
2491  #include "TargetConditionals.h"
2492  #if !defined(TARGET_OS_IPHONE) && !defined(OS_IOS) /* macOS */
2493  ret = system(cmd);
2494  #else
2495  L_ERROR("iOS 11 does not support system()\n", procName);
2496  #endif /* !TARGET_OS_IPHONE ... */
2497 
2498 #else /* ! OS_IOS */
2499 
2500  ret = system(cmd);
2501 
2502 #endif /* OS_IOS */
2503 }
2504 
2505 
2506 /*--------------------------------------------------------------------*
2507  * General file name operations *
2508  *--------------------------------------------------------------------*/
2539 l_ok
2540 splitPathAtDirectory(const char *pathname,
2541  char **pdir,
2542  char **ptail)
2543 {
2544 char *cpathname, *lastslash;
2545 
2546  PROCNAME("splitPathAtDirectory");
2547 
2548  if (!pdir && !ptail)
2549  return ERROR_INT("null input for both strings", procName, 1);
2550  if (pdir) *pdir = NULL;
2551  if (ptail) *ptail = NULL;
2552  if (!pathname)
2553  return ERROR_INT("pathname not defined", procName, 1);
2554 
2555  cpathname = stringNew(pathname);
2556  convertSepCharsInPath(cpathname, UNIX_PATH_SEPCHAR);
2557  lastslash = strrchr(cpathname, '/');
2558  if (lastslash) {
2559  if (ptail)
2560  *ptail = stringNew(lastslash + 1);
2561  if (pdir) {
2562  *(lastslash + 1) = '\0';
2563  *pdir = cpathname;
2564  } else {
2565  LEPT_FREE(cpathname);
2566  }
2567  } else { /* no directory */
2568  if (pdir)
2569  *pdir = stringNew("");
2570  if (ptail)
2571  *ptail = cpathname;
2572  else
2573  LEPT_FREE(cpathname);
2574  }
2575 
2576  return 0;
2577 }
2578 
2579 
2606 l_ok
2607 splitPathAtExtension(const char *pathname,
2608  char **pbasename,
2609  char **pextension)
2610 {
2611 char *tail, *dir, *lastdot;
2612 char empty[4] = "";
2613 
2614  PROCNAME("splitPathExtension");
2615 
2616  if (!pbasename && !pextension)
2617  return ERROR_INT("null input for both strings", procName, 1);
2618  if (pbasename) *pbasename = NULL;
2619  if (pextension) *pextension = NULL;
2620  if (!pathname)
2621  return ERROR_INT("pathname not defined", procName, 1);
2622 
2623  /* Split out the directory first */
2624  splitPathAtDirectory(pathname, &dir, &tail);
2625 
2626  /* Then look for a "." in the tail part.
2627  * This way we ignore all "." in the directory. */
2628  if ((lastdot = strrchr(tail, '.'))) {
2629  if (pextension)
2630  *pextension = stringNew(lastdot);
2631  if (pbasename) {
2632  *lastdot = '\0';
2633  *pbasename = stringJoin(dir, tail);
2634  }
2635  } else {
2636  if (pextension)
2637  *pextension = stringNew(empty);
2638  if (pbasename)
2639  *pbasename = stringNew(pathname);
2640  }
2641  LEPT_FREE(dir);
2642  LEPT_FREE(tail);
2643  return 0;
2644 }
2645 
2646 
2685 char *
2686 pathJoin(const char *dir,
2687  const char *fname)
2688 {
2689 const char *slash = "/";
2690 char *str, *dest;
2691 l_int32 i, n1, n2, emptydir;
2692 size_t size;
2693 SARRAY *sa1, *sa2;
2694 L_BYTEA *ba;
2695 
2696  PROCNAME("pathJoin");
2697 
2698  if (!dir && !fname)
2699  return stringNew("");
2700  if (dir && strlen(dir) >= 2 && dir[0] == '.' && dir[1] == '.')
2701  return (char *)ERROR_PTR("dir starts with '..'", procName, NULL);
2702  if (fname && strlen(fname) >= 2 && fname[0] == '.' && fname[1] == '.')
2703  return (char *)ERROR_PTR("fname starts with '..'", procName, NULL);
2704 
2705  sa1 = sarrayCreate(0);
2706  sa2 = sarrayCreate(0);
2707  ba = l_byteaCreate(4);
2708 
2709  /* Process %dir */
2710  if (dir && strlen(dir) > 0) {
2711  if (dir[0] == '/')
2712  l_byteaAppendString(ba, slash);
2713  sarraySplitString(sa1, dir, "/"); /* removes all slashes */
2714  n1 = sarrayGetCount(sa1);
2715  for (i = 0; i < n1; i++) {
2716  str = sarrayGetString(sa1, i, L_NOCOPY);
2717  l_byteaAppendString(ba, str);
2718  l_byteaAppendString(ba, slash);
2719  }
2720  }
2721 
2722  /* Special case to add leading slash: dir NULL or empty string */
2723  emptydir = dir && strlen(dir) == 0;
2724  if ((!dir || emptydir) && fname && strlen(fname) > 0 && fname[0] == '/')
2725  l_byteaAppendString(ba, slash);
2726 
2727  /* Process %fname */
2728  if (fname && strlen(fname) > 0) {
2729  sarraySplitString(sa2, fname, "/");
2730  n2 = sarrayGetCount(sa2);
2731  for (i = 0; i < n2; i++) {
2732  str = sarrayGetString(sa2, i, L_NOCOPY);
2733  l_byteaAppendString(ba, str);
2734  l_byteaAppendString(ba, slash);
2735  }
2736  }
2737 
2738  /* Remove trailing slash */
2739  dest = (char *)l_byteaCopyData(ba, &size);
2740  if (size > 1 && dest[size - 1] == '/')
2741  dest[size - 1] = '\0';
2742 
2743  sarrayDestroy(&sa1);
2744  sarrayDestroy(&sa2);
2745  l_byteaDestroy(&ba);
2746  return dest;
2747 }
2748 
2749 
2764 char *
2765 appendSubdirs(const char *basedir,
2766  const char *subdirs)
2767 {
2768 char *newdir;
2769 size_t len1, len2, len3, len4;
2770 
2771  PROCNAME("appendSubdirs");
2772 
2773  if (!basedir || !subdirs)
2774  return (char *)ERROR_PTR("basedir and subdirs not both defined",
2775  procName, NULL);
2776 
2777  len1 = strlen(basedir);
2778  len2 = strlen(subdirs);
2779  len3 = len1 + len2 + 6;
2780  if ((newdir = (char *)LEPT_CALLOC(len3 + 1, 1)) == NULL)
2781  return (char *)ERROR_PTR("newdir not made", procName, NULL);
2782  strncat(newdir, basedir, len3); /* add basedir */
2783  if (newdir[len1 - 1] != '/') /* add '/' if necessary */
2784  newdir[len1] = '/';
2785  if (subdirs[0] == '/') /* add subdirs, stripping leading '/' */
2786  strncat(newdir, subdirs + 1, len3);
2787  else
2788  strncat(newdir, subdirs, len3);
2789  len4 = strlen(newdir);
2790  if (newdir[len4 - 1] == '/') /* strip trailing '/' */
2791  newdir[len4 - 1] = '\0';
2792 
2793  return newdir;
2794 }
2795 
2796 
2797 /*--------------------------------------------------------------------*
2798  * Special file name operations *
2799  *--------------------------------------------------------------------*/
2816 l_ok
2818  l_int32 type)
2819 {
2820 l_int32 i;
2821 size_t len;
2822 
2823  PROCNAME("convertSepCharsInPath");
2824  if (!path)
2825  return ERROR_INT("path not defined", procName, 1);
2826  if (type != UNIX_PATH_SEPCHAR && type != WIN_PATH_SEPCHAR)
2827  return ERROR_INT("invalid type", procName, 1);
2828 
2829  len = strlen(path);
2830  if (type == UNIX_PATH_SEPCHAR) {
2831  for (i = 0; i < len; i++) {
2832  if (path[i] == '\\')
2833  path[i] = '/';
2834  }
2835  } else { /* WIN_PATH_SEPCHAR */
2836  for (i = 0; i < len; i++) {
2837  if (path[i] == '/')
2838  path[i] = '\\';
2839  }
2840  }
2841  return 0;
2842 }
2843 
2844 
2879 char *
2880 genPathname(const char *dir,
2881  const char *fname)
2882 {
2883 l_int32 is_win32 = FALSE;
2884 char *cdir, *pathout;
2885 l_int32 dirlen, namelen, size;
2886 
2887  PROCNAME("genPathname");
2888 
2889  if (!dir && !fname)
2890  return (char *)ERROR_PTR("no input", procName, NULL);
2891 
2892  /* Handle the case where we start from the current directory */
2893  if (!dir || dir[0] == '\0') {
2894  if ((cdir = getcwd(NULL, 0)) == NULL)
2895  return (char *)ERROR_PTR("no current dir found", procName, NULL);
2896  } else {
2897  cdir = stringNew(dir);
2898  }
2899 
2900  /* Convert to unix path separators, and remove the trailing
2901  * slash in the directory, except when dir == "/" */
2902  convertSepCharsInPath(cdir, UNIX_PATH_SEPCHAR);
2903  dirlen = strlen(cdir);
2904  if (cdir[dirlen - 1] == '/' && dirlen != 1) {
2905  cdir[dirlen - 1] = '\0';
2906  dirlen--;
2907  }
2908 
2909  namelen = (fname) ? strlen(fname) : 0;
2910  size = dirlen + namelen + 256;
2911  if ((pathout = (char *)LEPT_CALLOC(size, sizeof(char))) == NULL) {
2912  LEPT_FREE(cdir);
2913  return (char *)ERROR_PTR("pathout not made", procName, NULL);
2914  }
2915 
2916 #ifdef _WIN32
2917  is_win32 = TRUE;
2918 #endif /* _WIN32 */
2919 
2920  /* First handle %dir (which may be a full pathname).
2921  * There is no path rewriting on unix, and on win32, we do not
2922  * rewrite unless the specified directory is /tmp or
2923  * a subdirectory of /tmp */
2924  if (!is_win32 || dirlen < 4 ||
2925  (dirlen == 4 && strncmp(cdir, "/tmp", 4) != 0) || /* not in "/tmp" */
2926  (dirlen > 4 && strncmp(cdir, "/tmp/", 5) != 0)) { /* not in "/tmp/" */
2927  stringCopy(pathout, cdir, dirlen);
2928  } else { /* Rewrite for win32 with "/tmp" specified for the directory. */
2929 #ifdef _WIN32
2930  l_int32 tmpdirlen;
2931  char tmpdir[MAX_PATH];
2932  GetTempPath(sizeof(tmpdir), tmpdir); /* get the windows temp dir */
2933  tmpdirlen = strlen(tmpdir);
2934  if (tmpdirlen > 0 && tmpdir[tmpdirlen - 1] == '\\') {
2935  tmpdir[tmpdirlen - 1] = '\0'; /* trim the trailing '\' */
2936  }
2937  tmpdirlen = strlen(tmpdir);
2938  stringCopy(pathout, tmpdir, tmpdirlen);
2939 
2940  /* Add the rest of cdir */
2941  if (dirlen > 4)
2942  stringCat(pathout, size, cdir + 4);
2943 #endif /* _WIN32 */
2944  }
2945 
2946  /* Now handle %fname */
2947  if (fname && strlen(fname) > 0) {
2948  dirlen = strlen(pathout);
2949  pathout[dirlen] = '/';
2950  strncat(pathout, fname, namelen);
2951  }
2952 
2953  LEPT_FREE(cdir);
2954  return pathout;
2955 }
2956 
2957 
2985 l_ok
2986 makeTempDirname(char *result,
2987  size_t nbytes,
2988  const char *subdir)
2989 {
2990 char *dir, *path;
2991 l_int32 ret = 0;
2992 size_t pathlen;
2993 
2994  PROCNAME("makeTempDirname");
2995 
2996  if (!result)
2997  return ERROR_INT("result not defined", procName, 1);
2998  if (subdir && ((subdir[0] == '.') || (subdir[0] == '/')))
2999  return ERROR_INT("subdir not an actual subdirectory", procName, 1);
3000 
3001  memset(result, 0, nbytes);
3002  dir = pathJoin("/tmp", subdir);
3003 #ifndef _WIN32
3004  path = stringNew(dir);
3005 #else
3006  path = genPathname(dir, NULL);
3007 #endif /* ~ _WIN32 */
3008  pathlen = strlen(path);
3009  if (pathlen < nbytes - 1) {
3010  strncpy(result, path, pathlen);
3011  } else {
3012  L_ERROR("result array too small for path\n", procName);
3013  ret = 1;
3014  }
3015 
3016  LEPT_FREE(dir);
3017  LEPT_FREE(path);
3018  return ret;
3019 }
3020 
3021 
3035 l_ok
3037  size_t nbytes,
3038  l_int32 flag)
3039 {
3040 char lastchar;
3041 size_t len;
3042 
3043  PROCNAME("modifyTrailingSlash");
3044 
3045  if (!path)
3046  return ERROR_INT("path not defined", procName, 1);
3047  if (flag != L_ADD_TRAIL_SLASH && flag != L_REMOVE_TRAIL_SLASH)
3048  return ERROR_INT("invalid flag", procName, 1);
3049 
3050  len = strlen(path);
3051  lastchar = path[len - 1];
3052  if (flag == L_ADD_TRAIL_SLASH && lastchar != '/' && len < nbytes - 2) {
3053  path[len] = '/';
3054  path[len + 1] = '\0';
3055  } else if (flag == L_REMOVE_TRAIL_SLASH && lastchar == '/') {
3056  path[len - 1] = '\0';
3057  }
3058  return 0;
3059 }
3060 
3061 
3085 char *
3087 {
3088 char dirname[240];
3089 
3090  PROCNAME("l_makeTempFilename");
3091 
3092  if (makeTempDirname(dirname, sizeof(dirname), NULL) == 1)
3093  return (char *)ERROR_PTR("failed to make dirname", procName, NULL);
3094 
3095 #ifndef _WIN32
3096 {
3097  char *pattern;
3098  l_int32 fd;
3099  pattern = stringConcatNew(dirname, "/lept.XXXXXX", NULL);
3100  fd = mkstemp(pattern);
3101  if (fd == -1) {
3102  LEPT_FREE(pattern);
3103  return (char *)ERROR_PTR("mkstemp failed", procName, NULL);
3104  }
3105  close(fd);
3106  return pattern;
3107 }
3108 #else
3109 {
3110  char fname[MAX_PATH];
3111  FILE *fp;
3112  if (GetTempFileName(dirname, "lp.", 0, fname) == 0)
3113  return (char *)ERROR_PTR("GetTempFileName failed", procName, NULL);
3114  if ((fp = fopen(fname, "wb")) == NULL)
3115  return (char *)ERROR_PTR("file cannot be written to", procName, NULL);
3116  fclose(fp);
3117  return stringNew(fname);
3118 }
3119 #endif /* ~ _WIN32 */
3120 }
3121 
3122 
3141 l_int32
3142 extractNumberFromFilename(const char *fname,
3143  l_int32 numpre,
3144  l_int32 numpost)
3145 {
3146 char *tail, *basename;
3147 l_int32 len, nret, num;
3148 
3149  PROCNAME("extractNumberFromFilename");
3150 
3151  if (!fname)
3152  return ERROR_INT("fname not defined", procName, -1);
3153 
3154  splitPathAtDirectory(fname, NULL, &tail);
3155  splitPathAtExtension(tail, &basename, NULL);
3156  LEPT_FREE(tail);
3157 
3158  len = strlen(basename);
3159  if (numpre + numpost > len - 1) {
3160  LEPT_FREE(basename);
3161  return ERROR_INT("numpre + numpost too big", procName, -1);
3162  }
3163 
3164  basename[len - numpost] = '\0';
3165  nret = sscanf(basename + numpre, "%d", &num);
3166  LEPT_FREE(basename);
3167 
3168  if (nret == 1)
3169  return num;
3170  else
3171  return -1; /* not found */
3172 }
l_uint8 * l_binaryReadSelectStream(FILE *fp, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelectStream()
Definition: utils2.c:1374
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1471
l_int32 lept_mv(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_mv()
Definition: utils2.c:2298
l_int32 n
Definition: bbuffer.h:53
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
l_ok l_byteaAppendString(L_BYTEA *ba, const char *str)
l_byteaAppendString()
Definition: bytearray.c:395
l_int32 l_dnaGetCount(L_DNA *da)
l_dnaGetCount()
Definition: dnabasic.c:597
L_BBUFFER * bbufferCreate(const l_uint8 *indata, l_int32 nalloc)
bbufferCreate()
Definition: bbuffer.c:124
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2607
l_int32 stringLength(const char *src, size_t size)
stringLength()
Definition: utils2.c:373
l_ok stringCheckForChars(const char *src, const char *chars, l_int32 *pfound)
stringCheckForChars()
Definition: utils2.c:778
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition: utils2.c:2880
L_DNA * arrayFindEachSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen)
arrayFindEachSequence()
Definition: utils2.c:1032
L_BYTEA * l_byteaCreate(size_t nbytes)
l_byteaCreate()
Definition: bytearray.c:92
void l_dnaDestroy(L_DNA **pda)
l_dnaDestroy()
Definition: dnabasic.c:321
l_ok fileCopy(const char *srcfile, const char *newfile)
fileCopy()
Definition: utils2.c:1561
Definition: pix.h:716
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:215
char * appendSubdirs(const char *basedir, const char *subdirs)
appendSubdirs()
Definition: utils2.c:2765
l_uint8 * l_binaryReadSelect(const char *filename, size_t start, size_t nbytes, size_t *pnread)
l_binaryReadSelect()
Definition: utils2.c:1329
void * lept_calloc(size_t nmemb, size_t size)
lept_calloc()
Definition: utils2.c:1894
l_ok fileConcatenate(const char *srcfile, const char *destfile)
fileConcatenate()
Definition: utils2.c:1591
char * stringCopySegment(const char *src, l_int32 start, l_int32 nbytes)
stringCopySegment()
Definition: utils2.c:297
char * stringRemoveChars(const char *src, const char *remchars)
stringRemoveChars()
Definition: utils2.c:813
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:163
Definition: array.h:83
SARRAY * getFilenamesInDirectory(const char *dirname)
getFilenamesInDirectory()
Definition: sarray1.c:1859
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1734
l_int32 lept_cp(const char *srcfile, const char *newdir, const char *newtail, char **pnewpath)
lept_cp()
Definition: utils2.c:2397
l_uint8 * l_binaryCopy(l_uint8 *datas, size_t size)
l_binaryCopy()
Definition: utils2.c:1533
l_int32 lept_rm_match(const char *subdir, const char *substr)
lept_rm_match()
Definition: utils2.c:2153
l_ok l_dnaAddNumber(L_DNA *da, l_float64 val)
l_dnaAddNumber()
Definition: dnabasic.c:439
void * reallocNew(void **pindata, l_int32 oldsize, l_int32 newsize)
reallocNew()
Definition: utils2.c:1161
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition: utils2.c:3036
Definition: array.h:116
l_int32 stringCat(char *dest, size_t size, const char *src)
stringCat()
Definition: utils2.c:414
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1429
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1212
l_ok stringSplitOnToken(char *cstr, const char *seps, char **phead, char **ptail)
stringSplitOnToken()
Definition: utils2.c:734
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:564
void lept_free(void *ptr)
lept_free()
Definition: utils2.c:1915
l_ok fileAppendString(const char *filename, const char *str)
fileAppendString()
Definition: utils2.c:1619
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
Definition: utils2.c:1495
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
Definition: utils2.c:1780
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:681
char * stringReplaceEachSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *pcount)
stringReplaceEachSubstr()
Definition: utils2.c:977
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:337
void lept_direxists(const char *dir, l_int32 *pexists)
lept_direxists()
Definition: utils2.c:2095
SARRAY * getSortedPathnamesInDirectory(const char *dirname, const char *substr, l_int32 first, l_int32 nfiles)
getSortedPathnamesInDirectory()
Definition: sarray1.c:1717
l_int32 extractNumberFromFilename(const char *fname, l_int32 numpre, l_int32 numpost)
extractNumberFromFilename()
Definition: utils2.c:3142
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2540
void bbufferDestroy(L_BBUFFER **pbb)
bbufferDestroy()
Definition: bbuffer.c:167
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1700
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1657
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1262
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:621
FILE * lept_fopen(const char *filename, const char *mode)
lept_fopen()
Definition: utils2.c:1838
char * l_makeTempFilename()
l_makeTempFilename()
Definition: utils2.c:3086
l_ok lept_fclose(FILE *fp)
lept_fclose()
Definition: utils2.c:1868
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2686
L_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:169
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition: utils2.c:509
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition: utils2.c:2986
l_ok convertSepCharsInPath(char *path, l_int32 type)
convertSepCharsInPath()
Definition: utils2.c:2817
l_ok bbufferExtendArray(L_BBUFFER *bb, l_int32 nbytes)
bbufferExtendArray()
Definition: bbuffer.c:359
void callSystemDebug(const char *cmd)
callSystemDebug()
Definition: utils2.c:2474
char * strtokSafe(char *cstr, const char *seps, char **psaveptr)
strtokSafe()
Definition: utils2.c:640
void l_byteaDestroy(L_BYTEA **pba)
l_byteaDestroy()
Definition: bytearray.c:244
l_ok stringCopy(char *dest, const char *src, l_int32 n)
stringCopy()
Definition: utils2.c:255
l_int32 stringFindSubstr(const char *src, const char *sub, l_int32 *ploc)
stringFindSubstr()
Definition: utils2.c:858
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2021
char * stringReverse(const char *src)
stringReverse()
Definition: utils2.c:588
char * stringReplaceSubstr(const char *src, const char *sub1, const char *sub2, l_int32 *pfound, l_int32 *ploc)
stringReplaceSubstr()
Definition: utils2.c:910
l_int32 lept_rm(const char *subdir, const char *tail)
lept_rm()
Definition: utils2.c:2203
char * stringConcatNew(const char *first,...)
stringConcatNew()
Definition: utils2.c:462
l_uint8 * l_byteaCopyData(L_BYTEA *ba, size_t *psize)
l_byteaCopyData()
Definition: bytearray.c:332
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:1092
l_int32 lept_rmfile(const char *filepath)
lept_rmfile()
Definition: utils2.c:2243
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:355
Definition: array.h:126