📄 util.cpp
字号:
// $common\util.cpp 1.5 milbo$ util.c: utilities for an environment without windows on the screen// Warning: this is raw research code -- expect it to be quite messy.// milbo jul 05 petaluma#include <windows.h>#include <io.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <signal.h>#include <float.h>#include <math.h>#include <new.h>#include <direct.h>#include <sys/stat.h>#include <fstream.h>#include <iostream.h>#include "gsl/gsl_errno.h"#include "mcommon.hpp"#include "util.hpp"#include "err.hpp"extern void FreeNetworks(void);extern void CloseViolaJones(void);FILE *pgLogFile; // lprintfs go herebool fgUserInt; // non Windows only: true if user interrupted (hit Control C)static char gsBuf[CONF_nMaxPrintfLen]; // general purpose buffer//-----------------------------------------------------------------------------// Allocate a memory block for the printf function to use in case// of memory allocation failure; the printf function uses malloc.// The failsafe memory block must be visible globally because the// handle_program_memory_depletion function can take one argument only.char *pgFailsafe = new char[512];//-----------------------------------------------------------------------------// Called from within malloc or new if they fail. See the function Init().static int __cdecl HandleProgramMemoryDepletion (size_t size){delete pgFailsafe; // Release character buffer memory.// Could return 0 here to tell new to stop allocation attempts// but instead we are going to exit. We don't call SysErr because// it calls Shutdown and who knows what kind of memory allocation that// may need, thus causing recursive calls into here. Instead, we just exit.lprintf("\nSysErr: out of memory allocating %g megabytes\n", double(size) / (1024 * 1024));#if _DEBUGEnterDebugger;#endifexit(CONF_iSysErrExit);}//-----------------------------------------------------------------------------// The _matherr function processes errors generated in the math library.// Certain floating point function call _matherr when an error is detected.// By linking in this function we preclude the default library function.// Here we just print an error message and let the default library error handler// deal with it.static char *sMatherrType[] = {"unknown", "DOMAIN", "SING", "OVERFLOW", "UNDERFLOW", "TLOSS", "PLOSS"};int __cdecl _matherr (struct _exception *except){lprintf("\nMathErr: function %s(%g) type %s\n", except->name, except->arg1, sMatherrType[except->type]);#if _DEBUGif (CONF_fAbortOnMathErr) EnterDebugger;#endifreturn 0; // use the default action}//-----------------------------------------------------------------------------void GslErrorHandler (const char * reason, const char * file, int line, int gsl_errno){SysErr("%s:%d %s errno %d", file, line, reason, gsl_errno);}//-----------------------------------------------------------------------------// Like printf but prints to the log file as wellvoid __cdecl lprintf (const char *pArgs, ...) // args like printf{va_list pArg;va_start(pArg, pArgs);vsprintf(gsBuf, pArgs, pArg);va_end(pArg);printf("%s", gsBuf);fflush(stdout); // unneeded under Win98 but needed under WinXPif (pgLogFile) { fputs(gsBuf, pgLogFile); fflush(pgLogFile); // flush so if there's a crash we can see what happened }}//-----------------------------------------------------------------------------// Like printf but prints to the log file only (and not to screen)// Used for detailed stuff that we may want to know but we don't want to// usually bother the user withvoid __cdecl logprintf (const char *pArgs, ...) // args like printf{va_list pArg;if (pgLogFile) { va_start(pArg, pArgs); vsprintf(gsBuf, pArgs, pArg); va_end(pArg); fputs(gsBuf, pgLogFile); // no flush (for speed) }}//-----------------------------------------------------------------------------// Does a logprintf. If fBrief flag is clear, prints to screen as well.void __cdecl bprintf (bool fBrief, const char *pArgs, ...) // args like printf{va_list pArg;va_start(pArg, pArgs);vsprintf(gsBuf, pArgs, pArg);va_end(pArg);if (!fBrief) { printf("%s", gsBuf); fflush(stdout); // unneeded under Win98 but needed under WinXP }if (pgLogFile) { fputs(gsBuf, pgLogFile); fflush(pgLogFile); // flush so if there's a crash we can see what happened }}//-----------------------------------------------------------------------------// User interrupt (hit Control C or caused SIGINT in some other way).// Here we just set a flag. This keeps the system stable. It is up to everyone// else to poll the flag and to gracefully exit.static void __cdecl UserIntHandler (int Dummy){fgUserInt = true;lprintf("\nUser Interrupt\n");}//-----------------------------------------------------------------------------// Opens the log file.// When you call lprintf, you print on the screen and the log file.static void OpenLogFile (bool fVerbose, bool fAppendToLog, const char sLogFile[]){if (fAppendToLog) { if (fVerbose) printf("Appending to %s\n", sLogFile); pgLogFile = fopen(sLogFile, "a"); }else { if (fVerbose) printf("Logging to %s\n", sLogFile); pgLogFile = fopen(sLogFile, "w"); }if (!pgLogFile) { printf("\nCan't open \"%s\"\n", sLogFile); // Err() uses lprintf which uses the log file, so best just to exit on our own exit(CONF_iErrExit); }}//-----------------------------------------------------------------------------// This gets called once, at program start up.// See the entry for _set_new_handler in the Microsoft VC++ documentation.void Init (bool fVerbose, bool fAppendToLog, const char sLogFile[]){OpenLogFile(fVerbose, fAppendToLog, (sLogFile? sLogFile: sgLog));// assign the function that will be called if malloc or new fails_set_new_handler(HandleProgramMemoryDepletion);_set_new_mode(1);// assign the function that will be called if there is an error in the GSL routinesgsl_set_error_handler(GslErrorHandler);// assign the function that will be called if user hits control-Csignal(SIGINT, UserIntHandler);}//-----------------------------------------------------------------------------// This gets called once, at program terminationvoid Shutdown (void){if (pgLogFile) fclose(pgLogFile);pgLogFile = NULL;if (pgFailsafe) delete(pgFailsafe);pgFailsafe = NULL;}//-----------------------------------------------------------------------------// PacifyUser prints a progress digit every 10%//// To init: call InitPacifyUser with n = total loop count// To use: call this in loop repeatedly with i = current loop count//// This will print 0123456789// I usually terminate with a final 0, printed manually outside this routine.//// TODO this doesn't work well if n too small (<10?)static const int CONF_nPacifyPercent = 100/10; // pacify every 10%static int ngPacify;static int ngPacify1; // smallest nbr divisible by 10 but bigger than nstatic int ngPacifyPercent;void InitPacifyUser (int n){ngPacify = 0;ngPacifyPercent = CONF_nPacifyPercent;ngPacify1 = ((n + CONF_nPacifyPercent) / CONF_nPacifyPercent) * CONF_nPacifyPercent;}void PacifyUser (int i){if (i >= ngPacify) { printf("%d", (ngPacify * 10) / ngPacify1); fflush(stdout); ngPacify += ngPacify1 / ngPacifyPercent; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -