Leptonica 1.83.1
Image processing and image analysis suite
Loading...
Searching...
No Matches
utils1.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
105
106#ifdef HAVE_CONFIG_H
107#include <config_auto.h>
108#endif /* HAVE_CONFIG_H */
109
110#ifdef _WIN32
111#include <windows.h>
112#endif /* _WIN32 */
113
114#include <time.h>
115#include "allheaders.h"
116#include <math.h>
117
118 /* Global for controlling message output at runtime */
119LEPT_DLL l_int32 LeptMsgSeverity = DEFAULT_SEVERITY;
120
121#define DEBUG_SEV 0
122
123/*----------------------------------------------------------------------*
124 * Control of error, warning and info messages *
125 *----------------------------------------------------------------------*/
142l_int32
143setMsgSeverity(l_int32 newsev)
144{
145l_int32 oldsev;
146char *envsev;
147
148 oldsev = LeptMsgSeverity;
149 if (newsev == L_SEVERITY_EXTERNAL) {
150 envsev = getenv("LEPT_MSG_SEVERITY");
151 if (envsev) {
152 LeptMsgSeverity = atoi(envsev);
153#if DEBUG_SEV
154 L_INFO("message severity set to external\n", "setMsgSeverity");
155#endif /* DEBUG_SEV */
156 } else {
157#if DEBUG_SEV
158 L_WARNING("environment var LEPT_MSG_SEVERITY not defined\n",
159 "setMsgSeverity");
160#endif /* DEBUG_SEV */
161 }
162 } else {
163 LeptMsgSeverity = newsev;
164#if DEBUG_SEV
165 L_INFO("message severity set to %d\n", "setMsgSeverity", newsev);
166#endif /* DEBUG_SEV */
167 }
168
169 return oldsev;
170}
171
172
173/*----------------------------------------------------------------------*
174 * Error return functions, invoked by macros *
175 *----------------------------------------------------------------------*
176 * *
177 * (1) These error functions print messages to stderr and allow *
178 * exit from the function that called them. *
179 * (2) They must be invoked only by the macros ERROR_INT, *
180 * ERROR_FLOAT and ERROR_PTR, which are in environ.h *
181 * (3) The print output can be disabled at compile time, either *
182 * by using -DNO_CONSOLE_IO or by setting LeptMsgSeverity. *
183 *----------------------------------------------------------------------*/
192l_int32
193returnErrorInt(const char *msg,
194 const char *procname,
195 l_int32 ival)
196{
197 lept_stderr("Error in %s: %s\n", procname, msg);
198 return ival;
199}
200
201
210l_float32
211returnErrorFloat(const char *msg,
212 const char *procname,
213 l_float32 fval)
214{
215 lept_stderr("Error in %s: %s\n", procname, msg);
216 return fval;
217}
218
219
228void *
229returnErrorPtr(const char *msg,
230 const char *procname,
231 void *pval)
232{
233 lept_stderr("Error in %s: %s\n", procname, msg);
234 return pval;
235}
236
237
238/*------------------------------------------------------------------------*
239 * Runtime redirection of stderr *
240 *------------------------------------------------------------------------*
241 * *
242 * The user can provide a callback function to redirect messages *
243 * that would otherwise go to stderr. Here are two examples: *
244 * (1) to stop all messages: *
245 * void send_to_devnull(const char *msg) {} *
246 * (2) to write to the system logger: *
247 * void send_to_syslog(const char *msg) { *
248 * syslog(1, msg); *
249 * } *
250 * These would then be registered using *
251 * leptSetStderrHandler(send_to_devnull); *
252 * and *
253 * leptSetStderrHandler(send_to_syslog); *
254 *------------------------------------------------------------------------*/
255 /* By default, all messages go to stderr */
256static void lept_default_stderr_handler(const char *formatted_msg)
257{
258 if (formatted_msg)
259 fputs(formatted_msg, stderr);
260}
261
262 /* The stderr callback handler is private to leptonica.
263 * By default it writes to stderr. */
264void (*stderr_handler)(const char *) = lept_default_stderr_handler;
265
266
280void leptSetStderrHandler(void (*handler)(const char *))
281{
282 if (handler)
283 stderr_handler = handler;
284 else
285 stderr_handler = lept_default_stderr_handler;
286}
287
288
289#define MAX_DEBUG_MESSAGE 2000
306void lept_stderr(const char *fmt, ...)
307{
308va_list args;
309char msg[MAX_DEBUG_MESSAGE];
310l_int32 n;
311
312 va_start(args, fmt);
313 n = vsnprintf(msg, sizeof(msg), fmt, args);
314 va_end(args);
315 if (n < 0)
316 return;
317 (*stderr_handler)(msg);
318}
319
320
321/*--------------------------------------------------------------------*
322 * Test files for equivalence *
323 *--------------------------------------------------------------------*/
332l_ok
333filesAreIdentical(const char *fname1,
334 const char *fname2,
335 l_int32 *psame)
336{
337l_int32 i, same;
338size_t nbytes1, nbytes2;
339l_uint8 *array1, *array2;
340
341 if (!psame)
342 return ERROR_INT("&same not defined", __func__, 1);
343 *psame = 0;
344 if (!fname1 || !fname2)
345 return ERROR_INT("both names not defined", __func__, 1);
346
347 nbytes1 = nbytesInFile(fname1);
348 nbytes2 = nbytesInFile(fname2);
349 if (nbytes1 != nbytes2)
350 return 0;
351
352 if ((array1 = l_binaryRead(fname1, &nbytes1)) == NULL)
353 return ERROR_INT("array1 not read", __func__, 1);
354 if ((array2 = l_binaryRead(fname2, &nbytes2)) == NULL) {
355 LEPT_FREE(array1);
356 return ERROR_INT("array2 not read", __func__, 1);
357 }
358 same = 1;
359 for (i = 0; i < nbytes1; i++) {
360 if (array1[i] != array2[i]) {
361 same = 0;
362 break;
363 }
364 }
365 LEPT_FREE(array1);
366 LEPT_FREE(array2);
367 *psame = same;
368
369 return 0;
370}
371
372
373/*--------------------------------------------------------------------------*
374 * 16 and 32 bit byte-swapping on big endian and little endian machines *
375 *--------------------------------------------------------------------------*
376 * *
377 * These are typically used for I/O conversions: *
378 * (1) endian conversion for data that was read from a file *
379 * (2) endian conversion on data before it is written to a file *
380 *--------------------------------------------------------------------------*/
381
382/*--------------------------------------------------------------------*
383 * 16-bit byte swapping *
384 *--------------------------------------------------------------------*/
385#ifdef L_BIG_ENDIAN
386
387l_uint16
388convertOnBigEnd16(l_uint16 shortin)
389{
390 return ((shortin << 8) | (shortin >> 8));
391}
392
393l_uint16
394convertOnLittleEnd16(l_uint16 shortin)
395{
396 return shortin;
397}
398
399#else /* L_LITTLE_ENDIAN */
400
401l_uint16
402convertOnLittleEnd16(l_uint16 shortin)
403{
404 return ((shortin << 8) | (shortin >> 8));
405}
406
407l_uint16
408convertOnBigEnd16(l_uint16 shortin)
409{
410 return shortin;
411}
412
413#endif /* L_BIG_ENDIAN */
414
415
416/*--------------------------------------------------------------------*
417 * 32-bit byte swapping *
418 *--------------------------------------------------------------------*/
419#ifdef L_BIG_ENDIAN
420
421l_uint32
422convertOnBigEnd32(l_uint32 wordin)
423{
424 return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
425 ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
426}
427
428l_uint32
429convertOnLittleEnd32(l_uint32 wordin)
430{
431 return wordin;
432}
433
434#else /* L_LITTLE_ENDIAN */
435
436l_uint32
437convertOnLittleEnd32(l_uint32 wordin)
438{
439 return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
440 ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
441}
442
443l_uint32
444convertOnBigEnd32(l_uint32 wordin)
445{
446 return wordin;
447}
448
449#endif /* L_BIG_ENDIAN */
450
451
452/*---------------------------------------------------------------------*
453 * File corruption and byte replacement operations *
454 *---------------------------------------------------------------------*/
475l_ok
476fileCorruptByDeletion(const char *filein,
477 l_float32 loc,
478 l_float32 size,
479 const char *fileout)
480{
481l_int32 i, locb, sizeb, rembytes;
482size_t inbytes, outbytes;
483l_uint8 *datain, *dataout;
484
485 if (!filein || !fileout)
486 return ERROR_INT("filein and fileout not both specified", __func__, 1);
487 if (loc < 0.0 || loc >= 1.0)
488 return ERROR_INT("loc must be in [0.0 ... 1.0)", __func__, 1);
489 if (size <= 0.0)
490 return ERROR_INT("size must be > 0.0", __func__, 1);
491 if (loc + size > 1.0)
492 size = 1.0 - loc;
493
494 datain = l_binaryRead(filein, &inbytes);
495 locb = (l_int32)(loc * inbytes + 0.5);
496 locb = L_MIN(locb, inbytes - 1);
497 sizeb = (l_int32)(size * inbytes + 0.5);
498 sizeb = L_MAX(1, sizeb);
499 sizeb = L_MIN(sizeb, inbytes - locb); /* >= 1 */
500 L_INFO("Removed %d bytes at location %d\n", __func__, sizeb, locb);
501 rembytes = inbytes - locb - sizeb; /* >= 0; to be copied, after excision */
502
503 outbytes = inbytes - sizeb;
504 dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1);
505 for (i = 0; i < locb; i++)
506 dataout[i] = datain[i];
507 for (i = 0; i < rembytes; i++)
508 dataout[locb + i] = datain[locb + sizeb + i];
509 l_binaryWrite(fileout, "w", dataout, outbytes);
510
511 LEPT_FREE(datain);
512 LEPT_FREE(dataout);
513 return 0;
514}
515
516
537l_ok
538fileCorruptByMutation(const char *filein,
539 l_float32 loc,
540 l_float32 size,
541 const char *fileout)
542{
543l_int32 i, locb, sizeb;
544size_t bytes;
545l_uint8 *data;
546
547 if (!filein || !fileout)
548 return ERROR_INT("filein and fileout not both specified", __func__, 1);
549 if (loc < 0.0 || loc >= 1.0)
550 return ERROR_INT("loc must be in [0.0 ... 1.0)", __func__, 1);
551 if (size <= 0.0)
552 return ERROR_INT("size must be > 0.0", __func__, 1);
553 if (loc + size > 1.0)
554 size = 1.0 - loc;
555
556 data = l_binaryRead(filein, &bytes);
557 locb = (l_int32)(loc * bytes + 0.5);
558 locb = L_MIN(locb, bytes - 1);
559 sizeb = (l_int32)(size * bytes + 0.5);
560 sizeb = L_MAX(1, sizeb);
561 sizeb = L_MIN(sizeb, bytes - locb); /* >= 1 */
562 L_INFO("Randomizing %d bytes at location %d\n", __func__, sizeb, locb);
563
564 /* Make an array of random bytes and do the substitution */
565 for (i = 0; i < sizeb; i++) {
566 data[locb + i] =
567 (l_uint8)(255.9 * ((l_float64)rand() / (l_float64)RAND_MAX));
568 }
569
570 l_binaryWrite(fileout, "w", data, bytes);
571 LEPT_FREE(data);
572 return 0;
573}
574
575
596l_ok
597fileReplaceBytes(const char *filein,
598 l_int32 start,
599 l_int32 nbytes,
600 l_uint8 *newdata,
601 size_t newsize,
602 const char *fileout)
603{
604l_int32 i, index;
605size_t inbytes, outbytes;
606l_uint8 *datain, *dataout;
607
608 if (!filein || !fileout)
609 return ERROR_INT("filein and fileout not both specified", __func__, 1);
610
611 datain = l_binaryRead(filein, &inbytes);
612 if (start + nbytes > inbytes)
613 L_WARNING("start + nbytes > length(filein) = %zu\n", __func__, inbytes);
614
615 if (!newdata) newsize = 0;
616 outbytes = inbytes - nbytes + newsize;
617 if ((dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1)) == NULL) {
618 LEPT_FREE(datain);
619 return ERROR_INT("calloc fail for dataout", __func__, 1);
620 }
621
622 for (i = 0; i < start; i++)
623 dataout[i] = datain[i];
624 for (i = start; i < start + newsize; i++)
625 dataout[i] = newdata[i - start];
626 index = start + nbytes; /* for datain */
627 start += newsize; /* for dataout */
628 for (i = start; i < outbytes; i++, index++)
629 dataout[i] = datain[index];
630 l_binaryWrite(fileout, "w", dataout, outbytes);
631
632 LEPT_FREE(datain);
633 LEPT_FREE(dataout);
634 return 0;
635}
636
637
638/*---------------------------------------------------------------------*
639 * Generate random integer in given interval *
640 *---------------------------------------------------------------------*/
650l_ok
652 l_int32 end,
653 l_int32 seed,
654 l_int32 *pval)
655{
656l_float64 range;
657
658 if (!pval)
659 return ERROR_INT("&val not defined", __func__, 1);
660 *pval = 0;
661 if (end < start)
662 return ERROR_INT("invalid range", __func__, 1);
663
664 if (seed > 0) srand(seed);
665 range = (l_float64)(end - start + 1);
666 *pval = start + (l_int32)((l_float64)range *
667 ((l_float64)rand() / (l_float64)RAND_MAX));
668 return 0;
669}
670
671
672/*---------------------------------------------------------------------*
673 * Simple math function *
674 *---------------------------------------------------------------------*/
689l_int32
690lept_roundftoi(l_float32 fval)
691{
692 return (fval >= 0.0) ? (l_int32)(fval + 0.5) : (l_int32)(fval - 0.5);
693}
694
695
696/*---------------------------------------------------------------------*
697 * 64-bit hash functions *
698 *---------------------------------------------------------------------*/
721l_ok
722l_hashStringToUint64(const char *str,
723 l_uint64 *phash)
724{
725l_uint64 hash, mulp;
726
727 if (phash) *phash = 0;
728 if (!str || (str[0] == '\0'))
729 return ERROR_INT("str not defined or empty", __func__, 1);
730 if (!phash)
731 return ERROR_INT("&hash not defined", __func__, 1);
732
733 mulp = 26544357894361247; /* prime, about 1/700 of the max uint64 */
734 hash = 104395301;
735 while (*str) {
736 hash += (*str++ * mulp) ^ (hash >> 7); /* shift [1...23] are ok */
737 }
738 *phash = hash ^ (hash << 37);
739 return 0;
740}
741
742
758l_ok
760 l_uint64 *phash)
761{
762l_uint64 h;
763l_uint8 *p;
764
765 if (phash) *phash = 0;
766 if (!str || (str[0] == '\0'))
767 return ERROR_INT("str not defined or empty", __func__, 1);
768 if (!phash)
769 return ERROR_INT("&hash not defined", __func__, 1);
770
771 h = 0;
772 for (p = (l_uint8 *)str; *p != '\0'; p++)
773 h = 37 * h + *p; /* 37 is good prime number for this */
774 *phash = h;
775 return 0;
776}
777
778
792l_ok
794 l_int32 y,
795 l_uint64 *phash)
796{
797 if (!phash)
798 return ERROR_INT("&hash not defined", __func__, 1);
799
800 *phash = (l_uint64)(2173249142.3849 * x + 3763193258.6227 * y);
801 return 0;
802}
803
804
820l_ok
822 l_uint64 *phash)
823{
824 if (!phash)
825 return ERROR_INT("&hash not defined", __func__, 1);
826 val = (val >= 0.0) ? 847019.66701 * val : -217324.91613 * val;
827 *phash = (l_uint64)val;
828 return 0;
829}
830
831
832/*---------------------------------------------------------------------*
833 * Prime finders *
834 *---------------------------------------------------------------------*/
842l_ok
844 l_uint32 *pprime)
845{
846l_int32 i, is_prime;
847
848 if (!pprime)
849 return ERROR_INT("&prime not defined", __func__, 1);
850 *pprime = 0;
851 if (start <= 0)
852 return ERROR_INT("start must be > 0", __func__, 1);
853
854 for (i = start + 1; ; i++) {
855 lept_isPrime(i, &is_prime, NULL);
856 if (is_prime) {
857 *pprime = i;
858 return 0;
859 }
860 }
861
862 return ERROR_INT("prime not found!", __func__, 1);
863}
864
865
875l_ok
876lept_isPrime(l_uint64 n,
877 l_int32 *pis_prime,
878 l_uint32 *pfactor)
879{
880l_uint32 div;
881l_uint64 limit, ratio;
882
883 if (pis_prime) *pis_prime = 0;
884 if (pfactor) *pfactor = 0;
885 if (!pis_prime)
886 return ERROR_INT("&is_prime not defined", __func__, 1);
887 if (n <= 0)
888 return ERROR_INT("n must be > 0", __func__, 1);
889
890 if (n % 2 == 0) {
891 if (pfactor) *pfactor = 2;
892 return 0;
893 }
894
895 limit = (l_uint64)sqrt((l_float64)n);
896 for (div = 3; div < limit; div += 2) {
897 ratio = n / div;
898 if (ratio * div == n) {
899 if (pfactor) *pfactor = div;
900 return 0;
901 }
902 }
903
904 *pis_prime = 1;
905 return 0;
906}
907
908
909/*---------------------------------------------------------------------*
910 * Gray code conversion *
911 *---------------------------------------------------------------------*/
924l_uint32
926{
927 return (val >> 1) ^ val;
928}
929
930
937l_uint32
939{
940l_uint32 shift;
941
942 for (shift = 1; shift < 32; shift <<= 1)
943 val ^= val >> shift;
944 return val;
945}
946
947
948/*---------------------------------------------------------------------*
949 * Leptonica version number *
950 *---------------------------------------------------------------------*/
959char *
961{
962size_t bufsize = 100;
963
964 char *version = (char *)LEPT_CALLOC(bufsize, sizeof(char));
965
966#ifdef _MSC_VER
967 #ifdef _USRDLL
968 char dllStr[] = "DLL";
969 #else
970 char dllStr[] = "LIB";
971 #endif
972 #ifdef _DEBUG
973 char debugStr[] = "Debug";
974 #else
975 char debugStr[] = "Release";
976 #endif
977 #ifdef _M_IX86
978 char bitStr[] = " x86";
979 #elif _M_X64
980 char bitStr[] = " x64";
981 #else
982 char bitStr[] = "";
983 #endif
984 snprintf(version, bufsize, "leptonica-%d.%d.%d (%s, %s) [MSC v.%d %s %s%s]",
985 LIBLEPT_MAJOR_VERSION, LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION,
986 __DATE__, __TIME__, _MSC_VER, dllStr, debugStr, bitStr);
987
988#else
989
990 snprintf(version, bufsize, "leptonica-%d.%d.%d", LIBLEPT_MAJOR_VERSION,
991 LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION);
992
993#endif /* _MSC_VER */
994 return version;
995}
996
997
998/*---------------------------------------------------------------------*
999 * Timing procs *
1000 *---------------------------------------------------------------------*/
1001#if !defined(_WIN32) && !defined(__Fuchsia__)
1002
1003#include <sys/time.h>
1004#include <sys/resource.h>
1005
1006static struct rusage rusage_before;
1007static struct rusage rusage_after;
1008
1018void
1020{
1021 getrusage(RUSAGE_SELF, &rusage_before);
1022}
1023
1024l_float32
1025stopTimer(void)
1026{
1027l_int32 tsec, tusec;
1028
1029 getrusage(RUSAGE_SELF, &rusage_after);
1030
1031 tsec = rusage_after.ru_utime.tv_sec - rusage_before.ru_utime.tv_sec;
1032 tusec = rusage_after.ru_utime.tv_usec - rusage_before.ru_utime.tv_usec;
1033 return (tsec + ((l_float32)tusec) / 1000000.0);
1034}
1035
1036
1050L_TIMER
1052{
1053struct rusage *rusage_start;
1054
1055 rusage_start = (struct rusage *)LEPT_CALLOC(1, sizeof(struct rusage));
1056 getrusage(RUSAGE_SELF, rusage_start);
1057 return rusage_start;
1058}
1059
1060l_float32
1061stopTimerNested(L_TIMER rusage_start)
1062{
1063l_int32 tsec, tusec;
1064struct rusage rusage_stop;
1065
1066 getrusage(RUSAGE_SELF, &rusage_stop);
1067
1068 tsec = rusage_stop.ru_utime.tv_sec -
1069 ((struct rusage *)rusage_start)->ru_utime.tv_sec;
1070 tusec = rusage_stop.ru_utime.tv_usec -
1071 ((struct rusage *)rusage_start)->ru_utime.tv_usec;
1072 LEPT_FREE(rusage_start);
1073 return (tsec + ((l_float32)tusec) / 1000000.0);
1074}
1075
1076
1084void
1085l_getCurrentTime(l_int32 *sec,
1086 l_int32 *usec)
1087{
1088struct timeval tv;
1089
1090 gettimeofday(&tv, NULL);
1091 if (sec) *sec = (l_int32)tv.tv_sec;
1092 if (usec) *usec = (l_int32)tv.tv_usec;
1093}
1094
1095#elif defined(__Fuchsia__) /* resource.h not implemented on Fuchsia. */
1096
1097 /* Timer functions are used for testing and debugging, and
1098 * are stubbed out. If they are needed in the future, they
1099 * can be implemented in Fuchsia using the zircon syscall
1100 * zx_object_get_info() in ZX_INFOR_THREAD_STATS mode. */
1101void
1102startTimer(void)
1103{
1104}
1105
1106l_float32
1107stopTimer(void)
1108{
1109 return 0.0;
1110}
1111
1112L_TIMER
1113startTimerNested(void)
1114{
1115 return NULL;
1116}
1117
1118l_float32
1119stopTimerNested(L_TIMER rusage_start)
1120{
1121 return 0.0;
1122}
1123
1124void
1125l_getCurrentTime(l_int32 *sec,
1126 l_int32 *usec)
1127{
1128}
1129
1130#else /* _WIN32 : resource.h not implemented under Windows */
1131
1132 /* Note: if division by 10^7 seems strange, the time is expressed
1133 * as the number of 100-nanosecond intervals that have elapsed
1134 * since 12:00 A.M. January 1, 1601. */
1135
1136static ULARGE_INTEGER utime_before;
1137static ULARGE_INTEGER utime_after;
1138
1139void
1140startTimer(void)
1141{
1142HANDLE this_process;
1143FILETIME start, stop, kernel, user;
1144
1145 this_process = GetCurrentProcess();
1146
1147 GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1148
1149 utime_before.LowPart = user.dwLowDateTime;
1150 utime_before.HighPart = user.dwHighDateTime;
1151}
1152
1153l_float32
1154stopTimer(void)
1155{
1156HANDLE this_process;
1157FILETIME start, stop, kernel, user;
1158ULONGLONG hnsec; /* in units of hecto-nanosecond (100 ns) intervals */
1159
1160 this_process = GetCurrentProcess();
1161
1162 GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1163
1164 utime_after.LowPart = user.dwLowDateTime;
1165 utime_after.HighPart = user.dwHighDateTime;
1166 hnsec = utime_after.QuadPart - utime_before.QuadPart;
1167 return (l_float32)(signed)hnsec / 10000000.0;
1168}
1169
1170L_TIMER
1171startTimerNested(void)
1172{
1173HANDLE this_process;
1174FILETIME start, stop, kernel, user;
1175ULARGE_INTEGER *utime_start;
1176
1177 this_process = GetCurrentProcess();
1178
1179 GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1180
1181 utime_start = (ULARGE_INTEGER *)LEPT_CALLOC(1, sizeof(ULARGE_INTEGER));
1182 utime_start->LowPart = user.dwLowDateTime;
1183 utime_start->HighPart = user.dwHighDateTime;
1184 return utime_start;
1185}
1186
1187l_float32
1188stopTimerNested(L_TIMER utime_start)
1189{
1190HANDLE this_process;
1191FILETIME start, stop, kernel, user;
1192ULARGE_INTEGER utime_stop;
1193ULONGLONG hnsec; /* in units of 100 ns intervals */
1194
1195 this_process = GetCurrentProcess ();
1196
1197 GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1198
1199 utime_stop.LowPart = user.dwLowDateTime;
1200 utime_stop.HighPart = user.dwHighDateTime;
1201 hnsec = utime_stop.QuadPart - ((ULARGE_INTEGER *)utime_start)->QuadPart;
1202 LEPT_FREE(utime_start);
1203 return (l_float32)(signed)hnsec / 10000000.0;
1204}
1205
1206void
1207l_getCurrentTime(l_int32 *sec,
1208 l_int32 *usec)
1209{
1210ULARGE_INTEGER utime, birthunix;
1211FILETIME systemtime;
1212LONGLONG birthunixhnsec = 116444736000000000; /*in units of 100 ns */
1213LONGLONG usecs;
1214
1215 GetSystemTimeAsFileTime(&systemtime);
1216 utime.LowPart = systemtime.dwLowDateTime;
1217 utime.HighPart = systemtime.dwHighDateTime;
1218
1219 birthunix.LowPart = (DWORD) birthunixhnsec;
1220 birthunix.HighPart = birthunixhnsec >> 32;
1221
1222 usecs = (LONGLONG) ((utime.QuadPart - birthunix.QuadPart) / 10);
1223
1224 if (sec) *sec = (l_int32) (usecs / 1000000);
1225 if (usec) *usec = (l_int32) (usecs % 1000000);
1226}
1227
1228#endif
1229
1230
1245L_WALLTIMER *
1247{
1248L_WALLTIMER *timer;
1249
1250 timer = (L_WALLTIMER *)LEPT_CALLOC(1, sizeof(L_WALLTIMER));
1251 l_getCurrentTime(&timer->start_sec, &timer->start_usec);
1252 return timer;
1253}
1254
1261l_float32
1262stopWallTimer(L_WALLTIMER **ptimer)
1263{
1264l_int32 tsec, tusec;
1265L_WALLTIMER *timer;
1266
1267 if (!ptimer)
1268 return (l_float32)ERROR_FLOAT("&timer not defined", __func__, 0.0);
1269 timer = *ptimer;
1270 if (!timer)
1271 return (l_float32)ERROR_FLOAT("timer not defined", __func__, 0.0);
1272
1273 l_getCurrentTime(&timer->stop_sec, &timer->stop_usec);
1274 tsec = timer->stop_sec - timer->start_sec;
1275 tusec = timer->stop_usec - timer->start_usec;
1276 LEPT_FREE(timer);
1277 *ptimer = NULL;
1278 return (tsec + ((l_float32)tusec) / 1000000.0);
1279}
1280
1281
1294char *
1296{
1297char buf[128] = "", sep = 'Z';
1298l_int32 gmt_offset, relh, relm;
1299time_t ut, lt;
1300struct tm Tm;
1301struct tm *tptr = &Tm;
1302
1303 ut = time(NULL);
1304
1305 /* This generates a second "time_t" value by calling "gmtime" to
1306 fill in a "tm" structure expressed as UTC and then calling
1307 "mktime", which expects a "tm" structure expressed as the
1308 local time. The result is a value that is offset from the
1309 value returned by the "time" function by the local UTC offset.
1310 "tm_isdst" is set to -1 to tell "mktime" to determine for
1311 itself whether DST is in effect. This is necessary because
1312 "gmtime" always sets "tm_isdst" to 0, which would tell
1313 "mktime" to presume that DST is not in effect. */
1314#ifdef _WIN32
1315 #ifdef _MSC_VER
1316 gmtime_s(tptr, &ut);
1317 #else /* mingw */
1318 tptr = gmtime(&ut);
1319 #endif
1320#else
1321 gmtime_r(&ut, tptr);
1322#endif
1323 tptr->tm_isdst = -1;
1324 lt = mktime(tptr);
1325
1326 /* Calls "difftime" to obtain the resulting difference in seconds,
1327 * because "time_t" is an opaque type, per the C standard. */
1328 gmt_offset = (l_int32) difftime(ut, lt);
1329 if (gmt_offset > 0)
1330 sep = '+';
1331 else if (gmt_offset < 0)
1332 sep = '-';
1333 relh = L_ABS(gmt_offset) / 3600;
1334 relm = (L_ABS(gmt_offset) % 3600) / 60;
1335
1336#ifdef _WIN32
1337 #ifdef _MSC_VER
1338 localtime_s(tptr, &ut);
1339 #else /* mingw */
1340 tptr = localtime(&ut);
1341 #endif
1342#else
1343 localtime_r(&ut, tptr);
1344#endif
1345 strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tptr);
1346 sprintf(buf + 14, "%c%02d'%02d'", sep, relh, relm);
1347 return stringNew(buf);
1348}
l_ok fileCorruptByMutation(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByMutation()
Definition utils1.c:538
char * l_getFormattedDate(void)
l_getFormattedDate()
Definition utils1.c:1295
l_ok filesAreIdentical(const char *fname1, const char *fname2, l_int32 *psame)
filesAreIdentical()
Definition utils1.c:333
l_ok fileReplaceBytes(const char *filein, l_int32 start, l_int32 nbytes, l_uint8 *newdata, size_t newsize, const char *fileout)
fileReplaceBytes()
Definition utils1.c:597
l_float32 stopWallTimer(L_WALLTIMER **ptimer)
stopWallTimer()
Definition utils1.c:1262
void startTimer(void)
startTimer(), stopTimer()
Definition utils1.c:1019
l_ok l_hashStringToUint64Fast(const char *str, l_uint64 *phash)
l_hashStringToUint64Fast()
Definition utils1.c:759
l_ok genRandomIntOnInterval(l_int32 start, l_int32 end, l_int32 seed, l_int32 *pval)
genRandomIntOnInterval()
Definition utils1.c:651
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition utils1.c:306
l_ok lept_isPrime(l_uint64 n, l_int32 *pis_prime, l_uint32 *pfactor)
lept_isPrime()
Definition utils1.c:876
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition utils1.c:960
void leptSetStderrHandler(void(*handler)(const char *))
leptSetStderrHandler()
Definition utils1.c:280
l_float32 returnErrorFloat(const char *msg, const char *procname, l_float32 fval)
returnErrorFloat()
Definition utils1.c:211
l_ok findNextLargerPrime(l_int32 start, l_uint32 *pprime)
findNextLargerPrime()
Definition utils1.c:843
l_ok fileCorruptByDeletion(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByDeletion()
Definition utils1.c:476
l_ok l_hashStringToUint64(const char *str, l_uint64 *phash)
l_hashStringToUint64()
Definition utils1.c:722
void l_getCurrentTime(l_int32 *sec, l_int32 *usec)
l_getCurrentTime()
Definition utils1.c:1085
L_TIMER startTimerNested(void)
startTimerNested(), stopTimerNested()
Definition utils1.c:1051
l_int32 setMsgSeverity(l_int32 newsev)
setMsgSeverity()
Definition utils1.c:143
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition utils1.c:690
void * returnErrorPtr(const char *msg, const char *procname, void *pval)
returnErrorPtr()
Definition utils1.c:229
l_uint32 convertGrayCodeToInt(l_uint32 val)
convertGrayCodeToInt()
Definition utils1.c:938
l_int32 returnErrorInt(const char *msg, const char *procname, l_int32 ival)
returnErrorInt()
Definition utils1.c:193
L_WALLTIMER * startWallTimer(void)
startWallTimer()
Definition utils1.c:1246
l_uint32 convertIntToGrayCode(l_uint32 val)
convertIntToGrayCode()
Definition utils1.c:925
l_ok l_hashFloat64ToUint64(l_float64 val, l_uint64 *phash)
l_hashFloat64ToUint64()
Definition utils1.c:821
l_ok l_hashPtToUint64(l_int32 x, l_int32 y, l_uint64 *phash)
l_hashPtToUint64()
Definition utils1.c:793