1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                       */
3 /*    This file is part of the HiGHS linear optimization suite           */
4 /*                                                                       */
5 /*    Written and engineered 2008-2021 at the University of Edinburgh    */
6 /*                                                                       */
7 /*    Available as open-source under the MIT License                     */
8 /*                                                                       */
9 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10 /**@file io/HighsIO.cpp
11  * @brief IO methods for HiGHS - currently just print/log messages
12  * @author Julian Hall, Ivet Galabova, Qi Huangfu and Michael Feldmeier
13  */
14 #include "HighsIO.h"
15 
16 #include <cstdarg>
17 #include <cstdio>
18 #include <ctime>
19 
20 #include "lp_data/HighsLp.h"
21 #include "lp_data/HighsOptions.h"
22 
23 void (*printmsgcb)(int, const char*, void*) = NULL;
24 void (*logmsgcb)(HighsMessageType, const char*, void*) = NULL;
25 void* msgcb_data = NULL;
26 
27 char msgbuffer[65536];
28 
HighsPrintMessage(FILE * pass_output,const int pass_message_level,const int level,const char * format,...)29 void HighsPrintMessage(FILE* pass_output, const int pass_message_level,
30                        const int level, const char* format, ...) {
31   if (pass_output == NULL) {
32     return;
33   }
34   if (pass_message_level & level) {
35     va_list argptr;
36     va_start(argptr, format);
37     if (printmsgcb == NULL)
38       vfprintf(pass_output, format, argptr);
39     else {
40       int len;
41       len = vsnprintf(msgbuffer, sizeof(msgbuffer), format, argptr);
42       if (len >= (int)sizeof(msgbuffer)) {
43         // Output was truncated: for now just ensure string is null-terminated
44         msgbuffer[sizeof(msgbuffer) - 1] = '\0';
45       }
46       printmsgcb(level, msgbuffer, msgcb_data);
47     }
48     va_end(argptr);
49   }
50 }
51 
HighsLogMessage(FILE * pass_logfile,HighsMessageType type,const char * format,...)52 void HighsLogMessage(FILE* pass_logfile, HighsMessageType type,
53                      const char* format, ...) {
54   if (pass_logfile == NULL) {
55     return;
56   }
57 
58   time_t rawtime;
59   struct tm* timeinfo;
60 
61   time(&rawtime);
62   timeinfo = localtime(&rawtime);
63   va_list argptr;
64   va_start(argptr, format);
65 
66   if (logmsgcb == NULL) {
67     fprintf(pass_logfile, "%-7s: ", HighsMessageTypeTag[(int)type]);
68     vfprintf(pass_logfile, format, argptr);
69     fprintf(pass_logfile, "\n");
70   } else {
71     int len;
72     len = snprintf(msgbuffer, sizeof(msgbuffer), "%02d:%02d:%02d [%-7s] ",
73                    timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
74                    HighsMessageTypeTag[(int)type]);
75     if (len < (int)sizeof(msgbuffer))
76       len +=
77           vsnprintf(msgbuffer + len, sizeof(msgbuffer) - len, format, argptr);
78     if (len < (int)sizeof(msgbuffer) - 1) {
79       msgbuffer[len] = '\n';
80       ++len;
81       msgbuffer[len] = '\0';
82     } else
83       msgbuffer[sizeof(msgbuffer) - 1] = '\0';
84     logmsgcb(type, msgbuffer, msgcb_data);
85   }
86 
87   va_end(argptr);
88 }
89 
HighsSetMessageCallback(void (* printmsgcb_)(int level,const char * msg,void * msgcb_data),void (* logmsgcb_)(HighsMessageType type,const char * msg,void * msgcb_data),void * msgcb_data_)90 void HighsSetMessageCallback(
91     void (*printmsgcb_)(int level, const char* msg, void* msgcb_data),
92     void (*logmsgcb_)(HighsMessageType type, const char* msg, void* msgcb_data),
93     void* msgcb_data_) {
94   printmsgcb = printmsgcb_;
95   logmsgcb = logmsgcb_;
96   msgcb_data = msgcb_data_;
97 }
98 
HighsSetIO(HighsOptions & options)99 void HighsSetIO(HighsOptions& options) {
100   printmsgcb = options.printmsgcb;
101   logmsgcb = options.logmsgcb;
102   msgcb_data = options.msgcb_data;
103 }
104