1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 - This software is distributed in the hope that it will be
4 - useful, but with NO WARRANTY OF ANY KIND.
5 - No author or distributor accepts responsibility to anyone for the
6 - consequences of using this software, or for whether it serves any
7 - particular purpose or works at all, unless he or she says so in
8 - writing. Everyone is granted permission to copy, modify and
9 - redistribute this source code, for commercial or non-commercial
10 - purposes, with the following restrictions: (1) the origin of this
11 - source code must not be misrepresented; (2) modified versions must
12 - be plainly marked as such; and (3) this notice may not be removed
13 - or altered from any source or modified source distribution.
14 *====================================================================*/
15
16
17 /*
18 * utils.c
19 *
20 * error, warning and info procs; all invoked by macros
21 * l_int32 returnErrorInt()
22 * l_float32 returnErrorFloat()
23 * void *returnErrorPtr()
24 * void returnErrorVoid()
25 * void l_error()
26 * void l_errorString()
27 * void l_errorInt()
28 * void l_errorFloat()
29 * void l_warning()
30 * void l_warningString()
31 * void l_warningInt()
32 * void l_warningFloat()
33 * void l_info()
34 * void l_infoString()
35 * void l_infoInt()
36 * void l_infoInt2()
37 * void l_infoFloat()
38 * void l_infoFloat2()
39 *
40 * safe string procs
41 * char *stringNew()
42 * l_int32 stringReplace()
43 * char *stringJoin()
44 * char *stringReverse()
45 * char *strtokSafe()
46 * l_int32 stringSplitOnToken()
47 *
48 * find and replace procs
49 * char *stringRemoveChars()
50 * l_int32 stringFindSubstr()
51 * char *stringReplaceSubstr()
52 * char *stringReplaceEachSubstr()
53 * l_int32 arrayFindSequence()
54 *
55 * safe realloc
56 * void *reallocNew()
57 *
58 * read file to memory
59 * l_uint8 *arrayRead()
60 * l_uint8 *arrayReadStream()
61 * l_int32 nbytesInFile()
62 * l_int32 fnbytesInFile()
63 *
64 * write memory to file
65 * l_int32 arrayWrite()
66 *
67 * byte-swapping data conversion
68 * l_uint16 convertOnBigEnd16()
69 * l_uint32 convertOnBigEnd32()
70 * l_uint16 convertOnLittleEnd16()
71 * l_uint32 convertOnLittleEnd32()
72 *
73 * file opening
74 * FILE *fopenReadStream()
75 *
76 * file name operations
77 * l_int32 splitPathAtDirectory()
78 * l_int32 splitPathAtExtension()
79 * char *genPathname()
80 * char *genTempFilename()
81 * l_int32 extractNumberFromFilename()
82 *
83 * timing
84 * void startTimer()
85 * l_float32 stopTimer()
86 */
87
88 #include <stdio.h>
89 #include <string.h>
90 #include <stdlib.h>
91 #include <unistd.h>
92 #include "allheaders.h"
93
94 #if COMPILER_MSVC
95 static const char sepchar = '\\';
96 #else
97 static const char sepchar = '/';
98 #endif
99
100
101 /*----------------------------------------------------------------------*
102 * Error, warning and info message procs *
103 * *
104 * --------------------- N.B. --------------------- *
105 * *
106 * (1) These functions all print messages to stderr. *
107 * *
108 * (2) They must be invoked only by macros, which are in *
109 * environ.h, so that the print output can be disabled *
110 * at compile time, using -DNO_CONSOLE_IO. *
111 * *
112 *----------------------------------------------------------------------*/
113 /*!
114 * returnErrorInt()
115 *
116 * Input: msg (error message)
117 * procname
118 * ival (return val)
119 * Return: ival (typically 1)
120 */
121 l_int32
returnErrorInt(const char * msg,const char * procname,l_int32 ival)122 returnErrorInt(const char *msg,
123 const char *procname,
124 l_int32 ival)
125 {
126 fprintf(stderr, "Error in %s: %s\n", procname, msg);
127 return ival;
128 }
129
130
131 /*!
132 * returnErrorFloat()
133 *
134 * Input: msg (error message)
135 * procname
136 * fval (return val)
137 * Return: fval
138 */
139 l_float32
returnErrorFloat(const char * msg,const char * procname,l_float32 fval)140 returnErrorFloat(const char *msg,
141 const char *procname,
142 l_float32 fval)
143 {
144 fprintf(stderr, "Error in %s: %s\n", procname, msg);
145 return fval;
146 }
147
148
149 /*!
150 * returnErrorPtr()
151 *
152 * Input: msg (error message)
153 * procname
154 * pval (return val)
155 * Return: pval (typically null)
156 */
157 void *
returnErrorPtr(const char * msg,const char * procname,void * pval)158 returnErrorPtr(const char *msg,
159 const char *procname,
160 void *pval)
161 {
162 fprintf(stderr, "Error in %s: %s\n", procname, msg);
163 return pval;
164 }
165
166
167 /*!
168 * returnErrorVoid()
169 *
170 * Input: msg (error message)
171 * procname
172 */
173 void
returnErrorVoid(const char * msg,const char * procname)174 returnErrorVoid(const char *msg,
175 const char *procname)
176 {
177 fprintf(stderr, "Error in %s: %s\n", procname, msg);
178 return;
179 }
180
181
182 /*!
183 * l_error()
184 *
185 * Input: msg (error message)
186 * procname
187 */
188 void
l_error(const char * msg,const char * procname)189 l_error(const char *msg,
190 const char *procname)
191 {
192 fprintf(stderr, "Error in %s: %s\n", procname, msg);
193 return;
194 }
195
196
197 /*!
198 * l_errorString()
199 *
200 * Input: msg (error message; must include '%s')
201 * procname
202 * str (embedded in error message via %s)
203 */
204 void
l_errorString(const char * msg,const char * procname,const char * str)205 l_errorString(const char *msg,
206 const char *procname,
207 const char *str)
208 {
209 l_int32 bufsize;
210 char *charbuf;
211
212 if (!msg || !procname || !str) {
213 ERROR_VOID("msg, procname or str not defined in l_errorString()",
214 procname);
215 return;
216 }
217
218 bufsize = strlen(msg) + strlen(procname) + 128;
219 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
220 ERROR_VOID("charbuf not made in l_errorString()", procname);
221 return;
222 }
223
224 sprintf(charbuf, "Error in %s: %s\n", procname, msg);
225 fprintf(stderr, charbuf, str);
226
227 FREE(charbuf);
228 return;
229 }
230
231
232 /*!
233 * l_errorInt()
234 *
235 * Input: msg (error message; must include '%d')
236 * procname
237 * ival (embedded in error message via %d)
238 */
239 void
l_errorInt(const char * msg,const char * procname,l_int32 ival)240 l_errorInt(const char *msg,
241 const char *procname,
242 l_int32 ival)
243 {
244 l_int32 bufsize;
245 char *charbuf;
246
247 if (!msg || !procname) {
248 ERROR_VOID("msg or procname not defined in l_errorInt()", procname);
249 return;
250 }
251
252 bufsize = strlen(msg) + strlen(procname) + 128;
253 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
254 ERROR_VOID("charbuf not made in l_errorInt()", procname);
255 return;
256 }
257
258 sprintf(charbuf, "Error in %s: %s\n", procname, msg);
259 fprintf(stderr, charbuf, ival);
260
261 FREE(charbuf);
262 return;
263 }
264
265
266 /*!
267 * l_errorFloat()
268 *
269 * Input: msg (error message; must include '%f')
270 * procname
271 * fval (embedded in error message via %f)
272 */
273 void
l_errorFloat(const char * msg,const char * procname,l_float32 fval)274 l_errorFloat(const char *msg,
275 const char *procname,
276 l_float32 fval)
277 {
278 l_int32 bufsize;
279 char *charbuf;
280
281 if (!msg || !procname) {
282 ERROR_VOID("msg or procname not defined in l_errorFloat()", procname);
283 return;
284 }
285
286 bufsize = strlen(msg) + strlen(procname) + 128;
287 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
288 ERROR_VOID("charbuf not made in l_errorFloat()", procname);
289 return;
290 }
291
292 sprintf(charbuf, "Error in %s: %s\n", procname, msg);
293 fprintf(stderr, charbuf, fval);
294
295 FREE(charbuf);
296 return;
297 }
298
299
300 /*!
301 * l_warning()
302 *
303 * Input: msg (warning message)
304 * procname
305 */
306 void
l_warning(const char * msg,const char * procname)307 l_warning(const char *msg,
308 const char *procname)
309 {
310 fprintf(stderr, "Warning in %s: %s\n", procname, msg);
311 return;
312 }
313
314
315 /*!
316 * l_warningString()
317 *
318 * Input: msg (warning message; must include '%s')
319 * procname
320 * str (embedded in warning message via %s)
321 */
322 void
l_warningString(const char * msg,const char * procname,const char * str)323 l_warningString(const char *msg,
324 const char *procname,
325 const char *str)
326 {
327 l_int32 bufsize;
328 char *charbuf;
329
330 if (!msg || !procname || !str) {
331 ERROR_VOID("msg, procname or str not defined in l_warningString()",
332 procname);
333 return;
334 }
335
336 bufsize = strlen(msg) + strlen(procname) + 128;
337 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
338 ERROR_VOID("charbuf not made in l_warningString()", procname);
339 return;
340 }
341
342 sprintf(charbuf, "Warning in %s: %s\n", procname, msg);
343 fprintf(stderr, charbuf, str);
344
345 FREE(charbuf);
346 return;
347 }
348
349
350 /*!
351 * l_warningInt()
352 *
353 * Input: msg (warning message; must include '%d')
354 * procname
355 * ival (embedded in warning message via %d)
356 */
357 void
l_warningInt(const char * msg,const char * procname,l_int32 ival)358 l_warningInt(const char *msg,
359 const char *procname,
360 l_int32 ival)
361 {
362 l_int32 bufsize;
363 char *charbuf;
364
365 if (!msg || !procname) {
366 ERROR_VOID("msg or procname not defined in l_warningInt()", procname);
367 return;
368 }
369
370 bufsize = strlen(msg) + strlen(procname) + 128;
371 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
372 ERROR_VOID("charbuf not made in l_warningInt()", procname);
373 return;
374 }
375
376 sprintf(charbuf, "Warning in %s: %s\n", procname, msg);
377 fprintf(stderr, charbuf, ival);
378
379 FREE(charbuf);
380 return;
381 }
382
383
384 /*!
385 * l_warningFloat()
386 *
387 * Input: msg (warning message; must include '%f')
388 * procname
389 * fval (embedded in warning message via %f)
390 */
391 void
l_warningFloat(const char * msg,const char * procname,l_float32 fval)392 l_warningFloat(const char *msg,
393 const char *procname,
394 l_float32 fval)
395 {
396 l_int32 bufsize;
397 char *charbuf;
398
399 if (!msg || !procname) {
400 ERROR_VOID("msg or procname not defined in l_warningFloat()", procname);
401 return;
402 }
403
404 bufsize = strlen(msg) + strlen(procname) + 128;
405 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
406 ERROR_VOID("charbuf not made in l_warningFloat()", procname);
407 return;
408 }
409
410 sprintf(charbuf, "Warning in %s: %s\n", procname, msg);
411 fprintf(stderr, charbuf, fval);
412
413 FREE(charbuf);
414 return;
415 }
416
417
418 /*!
419 * l_info()
420 *
421 * Input: msg (info message)
422 * procname
423 */
424 void
l_info(const char * msg,const char * procname)425 l_info(const char *msg,
426 const char *procname)
427 {
428 fprintf(stderr, "Info in %s: %s\n", procname, msg);
429 return;
430 }
431
432
433 /*!
434 * l_infoString()
435 *
436 * Input: msg (info message; must include '%s')
437 * procname
438 * str (embedded in warning message via %s)
439 */
440 void
l_infoString(const char * msg,const char * procname,const char * str)441 l_infoString(const char *msg,
442 const char *procname,
443 const char *str)
444 {
445 l_int32 bufsize;
446 char *charbuf;
447
448 if (!msg || !procname || !str) {
449 ERROR_VOID("msg, procname or str not defined in l_infoString()",
450 procname);
451 return;
452 }
453
454 bufsize = strlen(msg) + strlen(procname) + 128;
455 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
456 ERROR_VOID("charbuf not made in l_infoString()", procname);
457 return;
458 }
459
460 sprintf(charbuf, "Info in %s: %s\n", procname, msg);
461 fprintf(stderr, charbuf, str);
462
463 FREE(charbuf);
464 return;
465 }
466
467
468 /*!
469 * l_infoInt()
470 *
471 * Input: msg (info message; must include '%d')
472 * procname
473 * ival (embedded in info message via %d)
474 */
475 void
l_infoInt(const char * msg,const char * procname,l_int32 ival)476 l_infoInt(const char *msg,
477 const char *procname,
478 l_int32 ival)
479 {
480 l_int32 bufsize;
481 char *charbuf;
482
483 if (!msg || !procname) {
484 ERROR_VOID("msg or procname not defined in l_infoInt()", procname);
485 return;
486 }
487
488 bufsize = strlen(msg) + strlen(procname) + 128;
489 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
490 ERROR_VOID("charbuf not made in l_infoInt()", procname);
491 return;
492 }
493
494 sprintf(charbuf, "Info in %s: %s\n", procname, msg);
495 fprintf(stderr, charbuf, ival);
496
497 FREE(charbuf);
498 return;
499 }
500
501
502 /*!
503 * l_infoInt2()
504 *
505 * Input: msg (info message; must include two '%d')
506 * procname
507 * ival1, ival2 (two args, embedded in info message via %d)
508 */
509 void
l_infoInt2(const char * msg,const char * procname,l_int32 ival1,l_int32 ival2)510 l_infoInt2(const char *msg,
511 const char *procname,
512 l_int32 ival1,
513 l_int32 ival2)
514 {
515 l_int32 bufsize;
516 char *charbuf;
517
518 if (!msg || !procname) {
519 ERROR_VOID("msg or procname not defined in l_infoInt2()", procname);
520 return;
521 }
522
523 bufsize = strlen(msg) + strlen(procname) + 128;
524 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
525 ERROR_VOID("charbuf not made in l_infoInt2()", procname);
526 return;
527 }
528
529 sprintf(charbuf, "Info in %s: %s\n", procname, msg);
530 fprintf(stderr, charbuf, ival1, ival2);
531
532 FREE(charbuf);
533 return;
534 }
535
536
537 /*!
538 * l_infoFloat()
539 *
540 * Input: msg (info message; must include '%f')
541 * procname
542 * fval (embedded in info message via %f)
543 */
544 void
l_infoFloat(const char * msg,const char * procname,l_float32 fval)545 l_infoFloat(const char *msg,
546 const char *procname,
547 l_float32 fval)
548 {
549 l_int32 bufsize;
550 char *charbuf;
551
552 if (!msg || !procname) {
553 ERROR_VOID("msg or procname not defined in l_infoFloat()", procname);
554 return;
555 }
556
557 bufsize = strlen(msg) + strlen(procname) + 128;
558 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
559 ERROR_VOID("charbuf not made in l_infoFloat()", procname);
560 return;
561 }
562
563 sprintf(charbuf, "Info in %s: %s\n", procname, msg);
564 fprintf(stderr, charbuf, fval);
565
566 FREE(charbuf);
567 return;
568 }
569
570
571 /*!
572 * l_infoFloat2()
573 *
574 * Input: msg (info message; must include two '%f')
575 * procname
576 * fval1, fval2 (two args, embedded in info message via %f)
577 */
578 void
l_infoFloat2(const char * msg,const char * procname,l_float32 fval1,l_float32 fval2)579 l_infoFloat2(const char *msg,
580 const char *procname,
581 l_float32 fval1,
582 l_float32 fval2)
583 {
584 l_int32 bufsize;
585 char *charbuf;
586
587 if (!msg || !procname) {
588 ERROR_VOID("msg or procname not defined in l_infoFloat2()", procname);
589 return;
590 }
591
592 bufsize = strlen(msg) + strlen(procname) + 128;
593 if ((charbuf = (char *)CALLOC(bufsize, sizeof(char))) == NULL) {
594 ERROR_VOID("charbuf not made in l_infoFloat()", procname);
595 return;
596 }
597
598 sprintf(charbuf, "Info in %s: %s\n", procname, msg);
599 fprintf(stderr, charbuf, fval1, fval2);
600
601 FREE(charbuf);
602 return;
603 }
604
605
606
607 /*--------------------------------------------------------------------*
608 * Safe string operations *
609 *--------------------------------------------------------------------*/
610 /*!
611 * stringNew()
612 *
613 * Input: src string
614 * Return: dest copy of src string, or null on error
615 */
616 char *
stringNew(const char * src)617 stringNew(const char *src)
618 {
619 char *dest;
620
621 PROCNAME("stringNew");
622
623 if (!src)
624 return (char *)ERROR_PTR("src not defined", procName, NULL);
625
626 if ((dest = (char *)CALLOC(strlen(src) + 2, sizeof(char))) == NULL)
627 return (char *)ERROR_PTR("dest not made", procName, NULL);
628 strcpy(dest, src);
629
630 return dest;
631 }
632
633
634 /*!
635 * stringReplace()
636 *
637 * Input: &dest string (<return> copy)
638 * src string
639 * Return: 0 if OK; 1 on error
640 *
641 * Notes:
642 * (1) Frees any existing dest string
643 * (2) Puts a copy of src string in the dest
644 * (3) If either or both strings are null, does the reasonable thing.
645 */
646 l_int32
stringReplace(char ** pdest,const char * src)647 stringReplace(char **pdest,
648 const char *src)
649 {
650 char *scopy;
651
652 PROCNAME("stringReplace");
653
654 if (!pdest)
655 return ERROR_INT("pdest not defined", procName, 1);
656
657 if (*pdest)
658 FREE(*pdest);
659
660 if (src) {
661 if ((scopy = (char *)CALLOC(strlen(src) + 2, sizeof(char))) == NULL)
662 return ERROR_INT("scopy not made", procName, 1);
663 strcpy(scopy, src);
664 *pdest = scopy;
665 }
666 else
667 *pdest = NULL;
668
669 return 0;
670 }
671
672
673 /*!
674 * stringJoin()
675 *
676 * Input: src1 string (<optional>)
677 * src2 string (<optional>)
678 * Return: concatenated string, or null on error
679 *
680 * Notes:
681 * (1) This is the safe version of strcat; it makes a new string.
682 * (2) It is not an error if either or both of the strings
683 * are empty, or if either or both the pointers are null.
684 */
685 char *
stringJoin(const char * src1,const char * src2)686 stringJoin(const char *src1,
687 const char *src2)
688 {
689 char *dest;
690 l_int32 srclen1, srclen2, destlen;
691
692 PROCNAME("stringJoin");
693
694 srclen1 = srclen2 = 0;
695 if (src1)
696 srclen1 = strlen(src1);
697 if (src2)
698 srclen2 = strlen(src2);
699 destlen = srclen1 + srclen2 + 3;
700
701 if ((dest = (char *)CALLOC(destlen, sizeof(char))) == NULL)
702 return (char *)ERROR_PTR("calloc fail for dest", procName, NULL);
703
704 if (src1)
705 strcpy(dest, src1);
706 if (src2)
707 strcat(dest, src2);
708 return dest;
709 }
710
711
712 /*!
713 * stringReverse()
714 *
715 * Input: src (string)
716 * Return: dest (newly-allocated reversed string)
717 */
718 char *
stringReverse(const char * src)719 stringReverse(const char *src)
720 {
721 char *dest;
722 l_int32 i, len;
723
724 PROCNAME("stringReverse");
725
726 if (!src)
727 return (char *)ERROR_PTR("src not defined", procName, NULL);
728 len = strlen(src);
729 if ((dest = (char *)CALLOC(len + 1, sizeof(char))) == NULL)
730 return (char *)ERROR_PTR("calloc fail for dest", procName, NULL);
731 for (i = 0; i < len; i++)
732 dest[i] = src[len - 1 - i];
733
734 return dest;
735 }
736
737
738 /*!
739 * strtokSafe()
740 *
741 * Input: cstr (input string to be sequentially parsed;
742 * use NULL after the first call)
743 * seps (a string of character separators)
744 * &saveptr (<return> ptr to the next char after
745 * the last encountered separator)
746 * Return: substr (a new string that is copied from the previous
747 * saveptr up to but not including the next
748 * separator character), or NULL if end of cstr.
749 *
750 * Notes:
751 * (1) This is a thread-safe implementation of strtok.
752 * (2) It has the same interface as strtok_r.
753 * (3) It differs from strtok_r in usage in two respects:
754 * (a) the input string is not altered
755 * (b) each returned substring is newly allocated and must
756 * be freed after use.
757 * (4) Let me repeat that. This is "safe" because the input
758 * string is not altered and because each returned string
759 * is newly allocated on the heap.
760 * (5) It is here because, surprisingly, some C libraries don't
761 * include strtok_r.
762 * (6) Important usage points:
763 * - Input the string to be parsed on the first invocation.
764 * - Then input NULL after that; the value returned in saveptr
765 * is used in all subsequent calls.
766 * (7) This is only slightly slower than strtok_k.
767 */
768 char *
strtokSafe(char * cstr,const char * seps,char ** psaveptr)769 strtokSafe(char *cstr,
770 const char *seps,
771 char **psaveptr)
772 {
773 char nextc;
774 char *start, *substr;
775 l_int32 istart, i, j, nchars;
776
777 PROCNAME("strtokSafe");
778
779 if (!seps)
780 return (char *)ERROR_PTR("seps not defined", procName, NULL);
781 if (!psaveptr)
782 return (char *)ERROR_PTR("&saveptr not defined", procName, NULL);
783
784 if (!cstr)
785 start = *psaveptr;
786 else
787 start = cstr;
788 if (!start) /* nothing to do */
789 return NULL;
790
791 /* First time, scan for the first non-sep character */
792 istart = 0;
793 if (cstr) {
794 for (istart = 0;; istart++) {
795 if ((nextc = start[istart]) == '\0') {
796 *psaveptr = NULL; /* in case caller doesn't check ret value */
797 return NULL;
798 }
799 if (!strchr(seps, nextc))
800 break;
801 }
802 }
803
804 /* Scan through, looking for a sep character; if none is
805 * found, 'i' will be at the end of the string. */
806 for (i = istart;; i++) {
807 if ((nextc = start[i]) == '\0')
808 break;
809 if (strchr(seps, nextc))
810 break;
811 }
812
813 /* Save the substring */
814 nchars = i - istart;
815 substr = (char *)CALLOC(nchars + 1, sizeof(char));
816 strncpy(substr, start + istart, nchars);
817
818 /* Look for the next non-sep character.
819 * If this is the last substring, return a null saveptr. */
820 for (j = i;; j++) {
821 if ((nextc = start[j]) == '\0') {
822 *psaveptr = NULL; /* no more non-sep characters */
823 break;
824 }
825 if (!strchr(seps, nextc)) {
826 *psaveptr = start + j; /* start here on next call */
827 break;
828 }
829 }
830
831 return substr;
832 }
833
834
835 /*!
836 * stringSplitOnToken()
837 *
838 * Input: cstr (input string to be split; not altered)
839 * seps (a string of character separators)
840 * &head (<return> ptr to copy of the input string, up to
841 * the first separator token encountered)
842 * &tail (<return> ptr to copy of the part of the input string
843 * starting with the first non-separator character
844 * that occurs after the first separator is found)
845 * Return: 0 if OK, 1 on error
846 *
847 * Notes:
848 * (1) The input string is not altered; all split parts are new strings.
849 * (2) The split occurs around the first consecutive sequence of
850 * tokens encountered.
851 * (3) The head goes from the beginning of the string up to
852 * but not including the first token found.
853 * (4) The tail contains the second part of the string, starting
854 * with the first char in that part that is NOT a token.
855 * (5) If no separator token is found, 'head' contains a copy
856 * of the input string and 'tail' is null.
857 */
858 l_int32
stringSplitOnToken(char * cstr,const char * seps,char ** phead,char ** ptail)859 stringSplitOnToken(char *cstr,
860 const char *seps,
861 char **phead,
862 char **ptail)
863 {
864 char *saveptr;
865
866 PROCNAME("stringSplitOnToken");
867
868 if (!phead)
869 return ERROR_INT("&head not defined", procName, 1);
870 if (!ptail)
871 return ERROR_INT("&tail not defined", procName, 1);
872 *phead = *ptail = NULL;
873 if (!cstr)
874 return ERROR_INT("cstr not defined", procName, 1);
875 if (!seps)
876 return ERROR_INT("seps not defined", procName, 1);
877
878 *phead = strtokSafe(cstr, seps, &saveptr);
879 if (saveptr)
880 *ptail = stringNew(saveptr);
881 return 0;
882 }
883
884
885 /*--------------------------------------------------------------------*
886 * Find and replace procs *
887 *--------------------------------------------------------------------*/
888 /*!
889 * stringRemoveChars()
890 *
891 * Input: src (input string; can be of zero length)
892 * remchars (string of chars to be removed from src)
893 * Return: dest (string with specified chars removed), or null on error
894 */
895 char *
stringRemoveChars(const char * src,const char * remchars)896 stringRemoveChars(const char *src,
897 const char *remchars)
898 {
899 char ch;
900 char *dest;
901 l_int32 nsrc, i, k;
902
903 PROCNAME("stringRemoveChars");
904
905 if (!src)
906 return (char *)ERROR_PTR("src not defined", procName, NULL);
907 if (!remchars)
908 return stringNew(src);
909
910 if ((dest = (char *)CALLOC(strlen(src) + 1, sizeof(char))) == NULL)
911 return (char *)ERROR_PTR("dest not made", procName, NULL);
912 nsrc = strlen(src);
913 for (i = 0, k = 0; i < nsrc; i++) {
914 ch = src[i];
915 if (!strchr(remchars, ch))
916 dest[k++] = ch;
917 }
918
919 return dest;
920 }
921
922
923 /*!
924 * stringFindSubstr()
925 *
926 * Input: src (input string; can be of zero length)
927 * sub (substring to be searched for)
928 * &loc (<return optional> location of substring in src)
929 * Return: 1 if found; 0 if not found or on error
930 *
931 * Notes:
932 * (1) This is a wrapper around strstr().
933 * (2) Both @src and @sub must be defined, and @sub must have
934 * length of at least 1.
935 * (3) If the substring is not found and loc is returned, it has
936 * the value -1.
937 */
938 l_int32
stringFindSubstr(const char * src,const char * sub,l_int32 * ploc)939 stringFindSubstr(const char *src,
940 const char *sub,
941 l_int32 *ploc)
942 {
943 char *ptr;
944
945 PROCNAME("stringFindSubstr");
946
947 if (!src)
948 return ERROR_INT("src not defined", procName, 0);
949 if (!sub)
950 return ERROR_INT("sub not defined", procName, 0);
951 if (ploc) *ploc = -1;
952 if (strlen(sub) == 0)
953 return ERROR_INT("substring length 0", procName, 0);
954 if (strlen(src) == 0)
955 return 0;
956
957 if ((ptr = (char *)strstr(src, sub)) == NULL) /* not found */
958 return 0;
959
960 if (*ploc)
961 *ploc = ptr - src;
962 return 1;
963 }
964
965
966 /*!
967 * stringReplaceSubstr()
968 *
969 * Input: src (input string; can be of zero length)
970 * sub1 (substring to be replaced)
971 * sub2 (substring to put in; can be "")
972 * &found (<return optional> 1 if sub1 is found; 0 otherwise)
973 * &loc (<return optional> location of ptr after replacement)
974 * Return: dest (string with substring replaced), or null if the
975 * substring not found or on error.
976 *
977 * Notes:
978 * (1) Replaces the first instance.
979 * (2) To only remove sub1, use "" for sub2
980 * (3) Returns a new string if sub1 and sub2 are the same.
981 * (4) The optional loc is input as the byte offset within the src
982 * from which the search starts, and after the search it is the
983 * char position in the string of the next character after
984 * the substituted string.
985 * (5) N.B. If ploc is not null, loc must always be initialized.
986 * To search the string from the beginning, set loc = 0.
987 */
988 char *
stringReplaceSubstr(const char * src,const char * sub1,const char * sub2,l_int32 * pfound,l_int32 * ploc)989 stringReplaceSubstr(const char *src,
990 const char *sub1,
991 const char *sub2,
992 l_int32 *pfound,
993 l_int32 *ploc)
994 {
995 char *ptr, *dest;
996 l_int32 nsrc, nsub1, nsub2, len, npre, loc;
997
998 PROCNAME("stringReplaceSubstr");
999
1000 if (!src)
1001 return (char *)ERROR_PTR("src not defined", procName, NULL);
1002 if (!sub1)
1003 return (char *)ERROR_PTR("sub1 not defined", procName, NULL);
1004 if (!sub2)
1005 return (char *)ERROR_PTR("sub2 not defined", procName, NULL);
1006
1007 if (pfound)
1008 *pfound = 0;
1009 if (ploc)
1010 loc = *ploc;
1011 else
1012 loc = 0;
1013 if ((ptr = (char *)strstr(src + loc, sub1)) == NULL) {
1014 return NULL;
1015 }
1016
1017 if (pfound)
1018 *pfound = 1;
1019 nsrc = strlen(src);
1020 nsub1 = strlen(sub1);
1021 nsub2 = strlen(sub2);
1022 len = nsrc + nsub2 - nsub1;
1023 if ((dest = (char *)CALLOC(len + 1, sizeof(char))) == NULL)
1024 return (char *)ERROR_PTR("dest not made", procName, NULL);
1025 npre = ptr - src;
1026 memcpy(dest, src, npre);
1027 strcpy(dest + npre, sub2);
1028 strcpy(dest + npre + nsub2, ptr + nsub1);
1029 if (ploc)
1030 *ploc = npre + nsub2;
1031
1032 return dest;
1033 }
1034
1035
1036 /*!
1037 * stringReplaceEachSubstr()
1038 *
1039 * Input: src (input string; can be of zero length)
1040 * sub1 (substring to be replaced)
1041 * sub2 (substring to put in; can be "")
1042 * &count (<optional return > the number of times that sub1
1043 * is found in src; 0 if not found)
1044 * Return: dest (string with substring replaced), or null if the
1045 * substring not found or on error.
1046 *
1047 * Notes:
1048 * (1) Replaces every instance.
1049 * (2) To only remove each instance of sub1, use "" for sub2
1050 * (3) Returns NULL if sub1 and sub2 are the same.
1051 */
1052 char *
stringReplaceEachSubstr(const char * src,const char * sub1,const char * sub2,l_int32 * pcount)1053 stringReplaceEachSubstr(const char *src,
1054 const char *sub1,
1055 const char *sub2,
1056 l_int32 *pcount)
1057 {
1058 char *currstr, *newstr;
1059 l_int32 loc;
1060
1061 PROCNAME("stringReplaceEachSubstr");
1062
1063 if (!src)
1064 return (char *)ERROR_PTR("src not defined", procName, NULL);
1065 if (!sub1)
1066 return (char *)ERROR_PTR("sub1 not defined", procName, NULL);
1067 if (!sub2)
1068 return (char *)ERROR_PTR("sub2 not defined", procName, NULL);
1069
1070 if (pcount)
1071 *pcount = 0;
1072 loc = 0;
1073 if ((newstr = stringReplaceSubstr(src, sub1, sub2, NULL, &loc)) == NULL)
1074 return NULL;
1075
1076 if (pcount)
1077 (*pcount)++;
1078 while (1) {
1079 currstr = newstr;
1080 newstr = stringReplaceSubstr(currstr, sub1, sub2, NULL, &loc);
1081 if (!newstr)
1082 return currstr;
1083 FREE(currstr);
1084 if (pcount)
1085 (*pcount)++;
1086 }
1087 }
1088
1089
1090 /*!
1091 * arrayFindSequence()
1092 *
1093 * Input: data (byte array)
1094 * datalen (length of data, in bytes)
1095 * sequence (subarray of bytes to find in data)
1096 * seqlen (length of sequence, in bytes)
1097 * &offset (return> offset from beginning of
1098 * data where the sequence begins)
1099 * &found (<return> 1 if sequence is found; 0 otherwise)
1100 * Return: 0 if OK, 1 on error
1101 *
1102 * Notes:
1103 * (1) The byte arrays 'data' and 'sequence' are not C strings,
1104 * as they can contain null bytes. Therefore, for each
1105 * we must give the length of the array.
1106 * (2) This searches for the first occurrence in 'data' of
1107 * the first 'seqlen' bytes of 'sequence'. The parameter 'seqlen'
1108 * must not exceed the actual length of the 'sequence' byte array.
1109 * (3) If the sequence is not found, the offset will be set to -1.
1110 */
1111 l_int32
arrayFindSequence(const l_uint8 * data,l_int32 datalen,const l_uint8 * sequence,l_int32 seqlen,l_int32 * poffset,l_int32 * pfound)1112 arrayFindSequence(const l_uint8 *data,
1113 l_int32 datalen,
1114 const l_uint8 *sequence,
1115 l_int32 seqlen,
1116 l_int32 *poffset,
1117 l_int32 *pfound)
1118 {
1119 l_int32 i, j, found, lastpos;
1120
1121 PROCNAME("arrayFindSequence");
1122
1123 if (!data || !sequence)
1124 return ERROR_INT("data & sequence not both defined", procName, 1);
1125 if (!poffset || !pfound)
1126 return ERROR_INT("&offset and &found not both defined", procName, 1);
1127
1128 *pfound = 0;
1129 *poffset = -1;
1130 lastpos = datalen - seqlen + 1;
1131 found = 0;
1132 for (i = 0; i < lastpos; i++) {
1133 for (j = 0; j < seqlen; j++) {
1134 if (data[i + j] != sequence[j])
1135 break;
1136 if (j == seqlen - 1)
1137 found = 1;
1138 }
1139 if (found)
1140 break;
1141 }
1142
1143 if (found) {
1144 *pfound = 1;
1145 *poffset = i;
1146 }
1147
1148 return 0;
1149 }
1150
1151
1152 /*--------------------------------------------------------------------*
1153 * Safe realloc *
1154 *--------------------------------------------------------------------*/
1155 /*!
1156 * reallocNew()
1157 *
1158 * Input: &indata (<optional>; nulls indata)
1159 * size of input data to be copied (bytes)
1160 * size of data to be reallocated (bytes)
1161 * Return: ptr to new data, or null on error
1162 *
1163 * Action: !N.B. (3) and (4)!
1164 * (1) Allocates memory, initialized to 0
1165 * (2) Copies as much of the input data as possible
1166 * to the new block, truncating the copy if necessary
1167 * (3) Frees the input data
1168 * (4) Zeroes the input data ptr
1169 *
1170 * Notes:
1171 * (1) If newsize <=0, just frees input data and nulls ptr
1172 * (2) If input ptr is null, just callocs new memory
1173 * (3) This differs from realloc in that it always allocates
1174 * new memory (if newsize > 0) and initializes it to 0,
1175 * it requires the amount of old data to be copied,
1176 * and it takes the address of the input ptr and
1177 * nulls the handle.
1178 */
1179 void *
reallocNew(void ** pindata,l_int32 oldsize,l_int32 newsize)1180 reallocNew(void **pindata,
1181 l_int32 oldsize,
1182 l_int32 newsize)
1183 {
1184 l_int32 minsize;
1185 void *indata;
1186 void *newdata;
1187
1188 PROCNAME("reallocNew");
1189
1190 if (!pindata)
1191 return ERROR_PTR("input data not defined", procName, NULL);
1192 indata = *pindata;
1193
1194 if (newsize <= 0) { /* nonstandard usage */
1195 if (indata) {
1196 FREE(indata);
1197 *pindata = NULL;
1198 }
1199 return NULL;
1200 }
1201
1202 if (!indata) /* nonstandard usage */
1203 {
1204 if ((newdata = (void *)CALLOC(1, newsize)) == NULL)
1205 return ERROR_PTR("newdata not made", procName, NULL);
1206 return newdata;
1207 }
1208
1209 /* Standard usage */
1210 if ((newdata = (void *)CALLOC(1, newsize)) == NULL)
1211 return ERROR_PTR("newdata not made", procName, NULL);
1212 minsize = L_MIN(oldsize, newsize);
1213 memcpy((char *)newdata, (char *)indata, minsize);
1214
1215 FREE(indata);
1216 *pindata = NULL;
1217
1218 return newdata;
1219 }
1220
1221
1222
1223 /*--------------------------------------------------------------------*
1224 * Reading bytes from file *
1225 *--------------------------------------------------------------------*/
1226 /*!
1227 * arrayRead()
1228 *
1229 * Input: filename
1230 * &nbytes (<return> number of bytes read)
1231 * Return: array, or null on error
1232 */
1233 l_uint8 *
arrayRead(const char * fname,l_int32 * pnbytes)1234 arrayRead(const char *fname,
1235 l_int32 *pnbytes)
1236 {
1237 l_uint8 *data;
1238 FILE *fp;
1239
1240 PROCNAME("arrayRead");
1241
1242 if (!fname)
1243 return (l_uint8 *)ERROR_PTR("fname not defined", procName, NULL);
1244 if (!pnbytes)
1245 return (l_uint8 *)ERROR_PTR("pnbytes not defined", procName, NULL);
1246 *pnbytes = 0;
1247
1248 if ((fp = fopen(fname, "r")) == NULL)
1249 return (l_uint8 *)ERROR_PTR("file stream not opened", procName, NULL);
1250
1251 data = arrayReadStream(fp, pnbytes);
1252 fclose(fp);
1253
1254 return data;
1255 }
1256
1257
1258 /*!
1259 * arrayReadStream()
1260 *
1261 * Input: stream
1262 * &nbytes (<return> number of bytes read)
1263 * Return: null-terminated array, or null on error
1264 * (reading 0 bytes is not an error)
1265 *
1266 * Notes:
1267 * (1) N.B.: as a side effect, this always re-positions the
1268 * stream ptr to the beginning of the file.
1269 */
1270 l_uint8 *
arrayReadStream(FILE * fp,l_int32 * pnbytes)1271 arrayReadStream(FILE *fp,
1272 l_int32 *pnbytes)
1273 {
1274 l_uint8 *data;
1275
1276 PROCNAME("arrayReadStream");
1277
1278 if (!fp)
1279 return (l_uint8 *)ERROR_PTR("stream not defined", procName, NULL);
1280 if (!pnbytes)
1281 return (l_uint8 *)ERROR_PTR("ptr to nbytes not defined", procName, NULL);
1282
1283 *pnbytes = fnbytesInFile(fp);
1284
1285 if ((data = (l_uint8 *)CALLOC(1, *pnbytes + 1)) == NULL)
1286 return (l_uint8 *)ERROR_PTR("CALLOC fail for data", procName, NULL);
1287 fread(data, *pnbytes, 1, fp);
1288
1289 return data;
1290 }
1291
1292
1293 /*!
1294 * nbytesInFile()
1295 *
1296 * Input: filename
1297 * Return: nbytes in file; 0 on error
1298 */
1299 l_int32
nbytesInFile(const char * filename)1300 nbytesInFile(const char *filename)
1301 {
1302 l_int32 nbytes;
1303 FILE *fp;
1304
1305 PROCNAME("nbytesInFile");
1306
1307 if (!filename)
1308 return ERROR_INT("filename not defined", procName, 0);
1309 fp = fopen(filename, "r");
1310 nbytes = fnbytesInFile(fp);
1311 fclose(fp);
1312 return nbytes;
1313 }
1314
1315
1316 /*!
1317 * fnbytesInFile()
1318 *
1319 * Input: file stream
1320 * Return: nbytes in file; 0 on error
1321 */
1322 l_int32
fnbytesInFile(FILE * fp)1323 fnbytesInFile(FILE *fp)
1324 {
1325 l_int32 nbytes, pos;
1326
1327 PROCNAME("fnbytesInFile");
1328
1329 if (!fp)
1330 return ERROR_INT("stream not open", procName, 0);
1331
1332 pos = ftell(fp); /* initial position */
1333 fseek(fp, 0, SEEK_END); /* EOF */
1334 nbytes = ftell(fp);
1335 fseek(fp, 0, pos); /* back to initial position */
1336 return nbytes;
1337 }
1338
1339
1340
1341 /*--------------------------------------------------------------------*
1342 * Writing bytes to file *
1343 *--------------------------------------------------------------------*/
1344 /*!
1345 * arrayWrite()
1346 *
1347 * Input: filename (output)
1348 * operation ("w" for write; "a" for append)
1349 * data (binary data to be written)
1350 * nbytes (size of data array)
1351 * Return: 0 if OK; 1 on error
1352 */
1353 l_int32
arrayWrite(const char * filename,const char * operation,void * data,l_int32 nbytes)1354 arrayWrite(const char *filename,
1355 const char *operation,
1356 void *data,
1357 l_int32 nbytes)
1358 {
1359 FILE *fp;
1360
1361 PROCNAME("arrayWrite");
1362
1363 if (!filename)
1364 return ERROR_INT("filename not defined", procName, 1);
1365 if (!operation)
1366 return ERROR_INT("operation not defined", procName, 1);
1367 if (!data)
1368 return ERROR_INT("data not defined", procName, 1);
1369 if (nbytes <= 0)
1370 return ERROR_INT("nbytes must be > 0", procName, 1);
1371
1372 if (!strcmp(operation, "w") && !strcmp(operation, "a"))
1373 return ERROR_INT("operation not one of {'w','a'}", procName, 1);
1374
1375 if ((fp = fopen(filename, operation)) == NULL)
1376 return ERROR_INT("stream not opened", procName, 1);
1377 fwrite(data, 1, nbytes, fp);
1378 fclose(fp);
1379
1380 return 0;
1381 }
1382
1383
1384 /*--------------------------------------------------------------------------*
1385 * 16 and 32 bit byte-swapping on big endian and little endian machines *
1386 * *
1387 * These are typically used for I/O conversions: *
1388 * (1) endian conversion for data that was read from a file *
1389 * (2) endian conversion on data before it is written to a file *
1390 *--------------------------------------------------------------------------*/
1391
1392 /*--------------------------------------------------------------------*
1393 * 16-bit byte swapping *
1394 *--------------------------------------------------------------------*/
1395 #ifdef L_BIG_ENDIAN
1396
1397 l_uint16
convertOnBigEnd16(l_uint16 shortin)1398 convertOnBigEnd16(l_uint16 shortin)
1399 {
1400 return ((shortin << 8) | (shortin >> 8));
1401 }
1402
1403 l_uint16
convertOnLittleEnd16(l_uint16 shortin)1404 convertOnLittleEnd16(l_uint16 shortin)
1405 {
1406 return shortin;
1407 }
1408
1409 #else /* L_LITTLE_ENDIAN */
1410
1411 l_uint16
convertOnLittleEnd16(l_uint16 shortin)1412 convertOnLittleEnd16(l_uint16 shortin)
1413 {
1414 return ((shortin << 8) | (shortin >> 8));
1415 }
1416
1417 l_uint16
convertOnBigEnd16(l_uint16 shortin)1418 convertOnBigEnd16(l_uint16 shortin)
1419 {
1420 return shortin;
1421 }
1422
1423 #endif /* L_BIG_ENDIAN */
1424
1425
1426 /*--------------------------------------------------------------------*
1427 * 32-bit byte swapping *
1428 *--------------------------------------------------------------------*/
1429 #ifdef L_BIG_ENDIAN
1430
1431 l_uint32
convertOnBigEnd32(l_uint32 wordin)1432 convertOnBigEnd32(l_uint32 wordin)
1433 {
1434 return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
1435 ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
1436 }
1437
1438 l_uint32
convertOnLittleEnd32(l_uint32 wordin)1439 convertOnLittleEnd32(l_uint32 wordin)
1440 {
1441 return wordin;
1442 }
1443
1444 #else /* L_LITTLE_ENDIAN */
1445
1446 l_uint32
convertOnLittleEnd32(l_uint32 wordin)1447 convertOnLittleEnd32(l_uint32 wordin)
1448 {
1449 return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
1450 ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
1451 }
1452
1453 l_uint32
convertOnBigEnd32(l_uint32 wordin)1454 convertOnBigEnd32(l_uint32 wordin)
1455 {
1456 return wordin;
1457 }
1458
1459 #endif /* L_BIG_ENDIAN */
1460
1461
1462
1463 /*--------------------------------------------------------------------*
1464 * Opening read stream *
1465 *--------------------------------------------------------------------*/
1466 /*!
1467 * fopenReadStream()
1468 *
1469 * Input: filename
1470 * Return: stream or null on error
1471 */
1472 FILE *
fopenReadStream(const char * filename)1473 fopenReadStream(const char *filename)
1474 {
1475 char *tail;
1476 FILE *fp;
1477
1478 PROCNAME("fopenReadStream");
1479
1480 if (!filename)
1481 return (FILE *)ERROR_PTR("filename not defined", procName, NULL);
1482
1483 /* Try input filename */
1484 if ((fp = fopen(filename, "rb")))
1485 return fp;
1486
1487 /* Else, strip directory and try locally */
1488 splitPathAtDirectory(filename, NULL, &tail);
1489 if ((fp = fopen(tail, "rb"))) {
1490 FREE(tail);
1491 return fp;
1492 }
1493 FREE(tail);
1494
1495 return (FILE *)ERROR_PTR("file not found", procName, NULL);
1496 }
1497
1498
1499 /*--------------------------------------------------------------------*
1500 * File name operations *
1501 *--------------------------------------------------------------------*/
1502 /*!
1503 * splitPathAtDirectory()
1504 *
1505 * Input: pathname (full path; can be a directory)
1506 * &dir (<optional return> root directory name of
1507 * input path, including trailing '/')
1508 * &tail (<optional return> path tail, which is either
1509 * the file name within the root directory or
1510 * the last sub-directory in the path)
1511 * Return: 0 if OK, 1 on error
1512 *
1513 * Note: (1) if you only want the tail, input null for
1514 * the root directory ptr.
1515 * (2) if you only want the root directory name,
1516 * input null for the tail ptr.
1517 * (3) This function makes decisions based only on the lexical
1518 * structure of the input. Examples:
1519 * /usr/tmp/abc --> dir: /usr/tmp/ tail: abc
1520 * /usr/tmp/ --> dir: /usr/tmp/ tail: [empty string]
1521 * /usr/tmp --> dir: /usr/ tail: tmp
1522 */
1523 l_int32
splitPathAtDirectory(const char * pathname,char ** pdir,char ** ptail)1524 splitPathAtDirectory(const char *pathname,
1525 char **pdir,
1526 char **ptail)
1527 {
1528 char *cpathname, *lastslash;
1529
1530 PROCNAME("splitPathAtDirectory");
1531
1532 if (!pdir && !ptail)
1533 return ERROR_INT("null input for both strings", procName, 1);
1534 if (pdir) *pdir = NULL;
1535 if (ptail) *ptail = NULL;
1536 if (!pathname)
1537 return ERROR_INT("pathname not defined", procName, 1);
1538
1539 cpathname = stringNew(pathname);
1540 if ((lastslash = strrchr(cpathname, '/'))) {
1541 if (ptail)
1542 *ptail = stringNew(lastslash + 1);
1543 if (pdir) {
1544 *(lastslash + 1) = '\0';
1545 *pdir = cpathname;
1546 }
1547 else
1548 FREE(cpathname);
1549 }
1550 else { /* no directory */
1551 if (pdir)
1552 *pdir = stringNew("");
1553 if (ptail)
1554 *ptail = cpathname;
1555 else
1556 FREE(cpathname);
1557 }
1558
1559 return 0;
1560 }
1561
1562
1563 /*!
1564 * splitPathAtExtension()
1565 *
1566 * Input: pathname (full path; can be a directory)
1567 * &basename (<optional return> pathname not including the
1568 * last dot and characters after that)
1569 * &extension (<optional return> path extension, which is
1570 * the last dot and the characters after it. If
1571 * there is no extension, it returns the empty string)
1572 * Return: 0 if OK, 1 on error
1573 *
1574 * Notes:
1575 * (1) If you only want the extension, input null for the basename ptr.
1576 * (2) If you only want the basename without extension, input null
1577 * for the extension ptr.
1578 * (3) This function makes decisions based only on the lexical
1579 * structure of the input. Examples:
1580 * /usr/tmp/abc.jpg --> basename: /usr/tmp/abc ext: .jpg
1581 * /usr/tmp/.jpg --> basename: /usr/tmp/ tail: .jpg
1582 * /usr/tmp.jpg/ --> basename: /usr/tmp.jpg/ tail: [empty str]
1583 * ./.jpg --> basename: ./ tail: .jpg
1584 */
1585 l_int32
splitPathAtExtension(const char * pathname,char ** pbasename,char ** pextension)1586 splitPathAtExtension(const char *pathname,
1587 char **pbasename,
1588 char **pextension)
1589 {
1590 char *tail, *dir, *lastdot;
1591 char empty[4] = "";
1592
1593 PROCNAME("splitPathExtension");
1594
1595 if (!pbasename && !pextension)
1596 return ERROR_INT("null input for both strings", procName, 1);
1597 if (pbasename) *pbasename = NULL;
1598 if (pextension) *pextension = NULL;
1599 if (!pathname)
1600 return ERROR_INT("pathname not defined", procName, 1);
1601
1602 /* Split out the directory first */
1603 splitPathAtDirectory(pathname, &dir, &tail);
1604
1605 /* Then look for a "." in the tail part.
1606 * This way we ignore all "." in the directory. */
1607 if ((lastdot = strrchr(tail, '.'))) {
1608 if (pextension)
1609 *pextension = stringNew(lastdot);
1610 if (pbasename) {
1611 *lastdot = '\0';
1612 *pbasename = stringJoin(dir, tail);
1613 }
1614 }
1615 else {
1616 if (pextension)
1617 *pextension = stringNew(empty);
1618 if (pbasename)
1619 *pbasename = stringNew(pathname);
1620 }
1621 FREE(dir);
1622 FREE(tail);
1623 return 0;
1624 }
1625
1626
1627 /*!
1628 * genPathname()
1629 *
1630 * Input: dir (directory name, with or without trailing '/')
1631 * fname (file name within the directory)
1632 * Return: full pathname, or null on error
1633 */
1634 char *
genPathname(const char * dir,const char * fname)1635 genPathname(const char *dir,
1636 const char *fname)
1637 {
1638 char *charbuf;
1639 l_int32 dirlen, namelen;
1640
1641 PROCNAME("genPathname");
1642
1643 if (!dir)
1644 return (char *)ERROR_PTR("dir not defined", procName, NULL);
1645 if (!fname)
1646 return (char *)ERROR_PTR("fname not defined", procName, NULL);
1647
1648 dirlen = strlen(dir);
1649 namelen = strlen(fname);
1650 if ((charbuf = (char *)CALLOC(dirlen + namelen + 10, sizeof(char)))
1651 == NULL)
1652 return (char *)ERROR_PTR("charbuf not made", procName, NULL);
1653
1654 if (dir[dirlen - 1] != sepchar)
1655 #if COMPILER_MSVC
1656 sprintf(charbuf, "%s\\", dir);
1657 #else
1658 sprintf(charbuf, "%s/", dir);
1659 #endif
1660 else
1661 strcpy(charbuf, dir);
1662 strcat(charbuf, fname);
1663 return charbuf;
1664 }
1665
1666
1667 /*!
1668 * genTempFilename()
1669 *
1670 * Input: dir (directory name; use '.' for local dir; no trailing '/')
1671 * extension (<optional> filename extention with '.'; can be null)
1672 * Return: tempname (with pid embedded in file name), or null on error
1673 *
1674 * Notes:
1675 * (1) This function is useful when there can be more than one
1676 * process writing and reading temporary files. It will not
1677 * work properly when multiple threads from a single process call
1678 * this function. Furthermore, as with any function that
1679 * provides easily guessed temporary filenames, it is not designed
1680 * to be safe from an attack where the intruder is logged onto
1681 * the server.
1682 */
1683 char *
genTempFilename(const char * dir,const char * extension)1684 genTempFilename(const char *dir,
1685 const char *extension)
1686 {
1687 char buf[256];
1688 char *tempname;
1689 l_int32 pid, nchars;
1690
1691 PROCNAME("genTempFilename");
1692
1693 if (!dir)
1694 return (char *)ERROR_PTR("dir not defined", procName, NULL);
1695 pid = getpid();
1696 if (extension)
1697 nchars = strlen(extension);
1698 else
1699 nchars = 0;
1700
1701 #if COMPILER_MSVC
1702 snprintf(buf, 255 - nchars, "%s\\%d", dir, pid);
1703 #else
1704 snprintf(buf, 25 - nchars, "%s/%d", dir, pid);
1705 #endif
1706
1707 tempname = stringJoin(buf, extension);
1708 return tempname;
1709 }
1710
1711
1712 /*!
1713 * extractNumberFromFilename()
1714 *
1715 * Input: fname
1716 * numpre (number of characters before the digits to be found)
1717 * numpost (number of characters after the digits to be found)
1718 * Return: num (number embedded in the filename); -1 on error or if
1719 * not found
1720 */
1721 l_int32
extractNumberFromFilename(const char * fname,l_int32 numpre,l_int32 numpost)1722 extractNumberFromFilename(const char *fname,
1723 l_int32 numpre,
1724 l_int32 numpost)
1725 {
1726 char *tail, *basename;
1727 l_int32 len, nret, num;
1728
1729 PROCNAME("extractNumberFromFilename");
1730
1731 if (!fname)
1732 return ERROR_INT("fname not defined", procName, -1);
1733
1734 splitPathAtDirectory(fname, NULL, &tail);
1735 splitPathAtExtension(tail, &basename, NULL);
1736 FREE(tail);
1737
1738 len = strlen(basename);
1739 if (numpre + numpost > len - 1) {
1740 FREE(basename);
1741 return ERROR_INT("numpre + numpost too big", procName, -1);
1742 }
1743
1744 basename[len - numpost] = '\n';
1745 nret = sscanf(basename + numpre, "%d", &num);
1746 FREE(basename);
1747
1748 if (nret == 1)
1749 return num;
1750 else
1751 return ERROR_INT("no number found", procName, -1);
1752 }
1753
1754
1755
1756 /*---------------------------------------------------------------------*
1757 * Timing procs *
1758 *---------------------------------------------------------------------*/
1759 /*
1760 * Example of use:
1761 *
1762 * startTimer();
1763 * ....
1764 * fprintf(stderr, "Elapsed time = %7.3f sec\n", stopTimer());
1765 */
1766 #if !defined(__MINGW32__) && !defined(_WIN32)
1767
1768 #include <sys/time.h>
1769 #include <sys/resource.h>
1770
1771 static struct rusage rusage_before;
1772 static struct rusage rusage_after;
1773
1774 void
startTimer(void)1775 startTimer(void)
1776 {
1777 getrusage(RUSAGE_SELF, &rusage_before);
1778 }
1779
1780
1781 l_float32
stopTimer(void)1782 stopTimer(void)
1783 {
1784 l_int32 tsec, tusec;
1785
1786 getrusage(RUSAGE_SELF, &rusage_after);
1787
1788 tsec = rusage_after.ru_utime.tv_sec - rusage_before.ru_utime.tv_sec;
1789 tusec = rusage_after.ru_utime.tv_usec - rusage_before.ru_utime.tv_usec;
1790
1791 return (tsec + ((l_float32)tusec) / 1000000.0);
1792 }
1793
1794 #else /* __MINGW32__ : resource.h not implemented under MINGW */
1795
1796 #include <windows.h>
1797
1798 static ULARGE_INTEGER utime_before;
1799 static ULARGE_INTEGER utime_after;
1800
1801 void
startTimer(void)1802 startTimer(void)
1803 {
1804 HANDLE this_process;
1805 FILETIME start, stop, kernel, user;
1806
1807 this_process = GetCurrentProcess ();
1808
1809 GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1810
1811 utime_before.LowPart = user.dwLowDateTime;
1812 utime_before.HighPart = user.dwHighDateTime;
1813 }
1814
1815 l_float32
stopTimer(void)1816 stopTimer(void)
1817 {
1818 HANDLE this_process;
1819 FILETIME start, stop, kernel, user;
1820
1821 this_process = GetCurrentProcess ();
1822
1823 GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1824
1825 utime_after.LowPart = user.dwLowDateTime;
1826 utime_after.HighPart = user.dwHighDateTime;
1827
1828 return ((l_float32)(signed)(utime_after.QuadPart - utime_before.QuadPart) /
1829 10000000.0);
1830 }
1831
1832 #endif
1833