Commit 18c1194e7d762eae0686a0b8b3e01c55e7beb35a
1 parent
7fedf106
first working implementation of logger
Showing
2 changed files
with
624 additions
and
23 deletions
include/GLog.hpp
| ... | ... | @@ -20,40 +20,94 @@ |
| 20 | 20 | #define GLOG_HPP |
| 21 | 21 | |
| 22 | 22 | /* __ Includes ___________________________________________________________ */ |
| 23 | -#include <time.h> | |
| 24 | -#include <vector> | |
| 25 | 23 | #include <string> |
| 26 | -#include <iostream> | |
| 24 | + | |
| 25 | +/* __ Forward declarations _______________________________________________ */ | |
| 27 | 26 | |
| 28 | 27 | |
| 29 | 28 | /***********************************************************************//** |
| 30 | 29 | * @class GLog |
| 31 | 30 | * |
| 32 | 31 | * @brief Information logger interface defintion. |
| 32 | + * | |
| 33 | + * This class implements an interface for logging of text messages to the | |
| 34 | + * standard output and/or error streams and into an ASCII log file. It | |
| 35 | + * provides a C++ style interface (allowing to stream messages using code | |
| 36 | + * such as | |
| 37 | + * log << "This is a message"; | |
| 38 | + * and a C style interface that allows making use of C style text formating | |
| 39 | + * using code such as | |
| 40 | + * log("These are %d messages with %d items.", n, m); | |
| 41 | + * The logger interface implements an internal character buffer that is | |
| 42 | + * flushed once a maximum size parameter is exceeded. The buffer limit can | |
| 43 | + * be modified using the max_size() method; by default it is set to 8192 | |
| 44 | + * characters. Note that the buffer is flushed each time a carriage return | |
| 45 | + * occurs, irrespectively of the buffer size. | |
| 46 | + * The logger allows prepending of the current date and the task name. Note | |
| 47 | + * that the current date is the one that applies when the buffer is actually | |
| 48 | + * flushed, hence when a good precision in the date is required the maximum | |
| 49 | + * buffer length should be set to 0 (i.e. the buffer is flushed after each | |
| 50 | + * logging). | |
| 33 | 51 | ***************************************************************************/ |
| 34 | 52 | class GLog { |
| 35 | 53 | |
| 36 | - // I/O friends | |
| 37 | - friend std::ostream& operator<< (std::ostream& os, const GLog& log); | |
| 38 | - | |
| 39 | 54 | public: |
| 40 | 55 | // Constructors and destructors |
| 41 | 56 | GLog(void); |
| 57 | + GLog(const std::string& filename, bool clobber = false); | |
| 42 | 58 | GLog(const GLog& log); |
| 43 | 59 | ~GLog(void); |
| 44 | 60 | |
| 45 | 61 | // Operators |
| 46 | 62 | GLog& operator= (const GLog& log); |
| 63 | + void operator()(const char *msgFormat, ...); | |
| 64 | + GLog& operator<<(const std::string& value); | |
| 65 | + GLog& operator<<(const bool& value); | |
| 66 | + GLog& operator<<(const int& value); | |
| 67 | + GLog& operator<<(const double& value); | |
| 68 | + GLog& operator<<(const char& value); | |
| 69 | + GLog& operator<<(std::ostream& (*fn)(std::ostream&)); | |
| 47 | 70 | |
| 48 | 71 | // Methods |
| 49 | - | |
| 72 | + void clear(void); | |
| 73 | + int size(void) const; | |
| 74 | + void open(const std::string& filename, bool clobber = false); | |
| 75 | + void close(void); | |
| 76 | + void date(bool flag); | |
| 77 | + void cout(bool flag); | |
| 78 | + void cerr(bool flag); | |
| 79 | + void name(const std::string& name); | |
| 80 | + void max_size(int size); | |
| 81 | + void indent(int indent); | |
| 82 | + void header0(const std::string& arg) { header(arg, 0); } | |
| 83 | + void header1(const std::string& arg) { header(arg, 1); } | |
| 84 | + void header2(const std::string& arg) { header(arg, 2); } | |
| 85 | + bool date(void) const { return m_use_date; } | |
| 86 | + bool cout(void) const { return m_stdout; } | |
| 87 | + bool cerr(void) const { return m_stderr; } | |
| 88 | + std::string name(void) const { return m_name; } | |
| 89 | + int max_size(void) const { return m_max_length; } | |
| 90 | + int indent(void) const { return m_indent; } | |
| 91 | + | |
| 50 | 92 | protected: |
| 51 | 93 | // Protected methods |
| 52 | - void init_members(void); | |
| 53 | - void copy_members(const GLog& log); | |
| 54 | - void free_members(void); | |
| 94 | + void init_members(void); | |
| 95 | + void copy_members(const GLog& log); | |
| 96 | + void free_members(void); | |
| 97 | + void flush(bool force = false); | |
| 98 | + void header(const std::string& arg, int level); | |
| 99 | + std::string strdate(void); | |
| 55 | 100 | |
| 56 | 101 | // Protected data members |
| 102 | + int m_max_length; //!< Maximum buffer length | |
| 103 | + int m_indent; //!< Indentation of text | |
| 104 | + bool m_stdout; //!< Dump in standard output | |
| 105 | + bool m_stderr; //!< Dump in standard error | |
| 106 | + bool m_use_date; //!< Dump date in prefix | |
| 107 | + bool m_newline; //!< Signal beginning of new line | |
| 108 | + FILE* m_file; //!< Log file pointer | |
| 109 | + std::string m_name; //!< Name for prefix | |
| 110 | + std::string m_buffer; //!< Output string buffer | |
| 57 | 111 | }; |
| 58 | 112 | |
| 59 | 113 | #endif /* GLOG_HPP */ | ... | ... |
src/app/GLog.cpp
| ... | ... | @@ -17,7 +17,16 @@ |
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | 19 | /* __ Includes ___________________________________________________________ */ |
| 20 | +#ifdef HAVE_CONFIG_H | |
| 21 | +#include <config.h> | |
| 22 | +#endif | |
| 23 | +#include <string> | |
| 24 | +#include <iostream> | |
| 25 | +#include <sstream> | |
| 26 | +#include <time.h> | |
| 27 | +#include <stdarg.h> // for "va_list" type | |
| 20 | 28 | #include "GLog.hpp" |
| 29 | +#include "GTools.hpp" | |
| 21 | 30 | |
| 22 | 31 | /* __ Method name definitions ____________________________________________ */ |
| 23 | 32 | |
| ... | ... | @@ -48,6 +57,27 @@ GLog::GLog(void) |
| 48 | 57 | |
| 49 | 58 | |
| 50 | 59 | /***********************************************************************//** |
| 60 | + * @brief Log file constructor | |
| 61 | + * | |
| 62 | + * @param[in] filename Name of log file. | |
| 63 | + * @param[in] clobber If true overwrite any existing file, otherwise append. | |
| 64 | + * | |
| 65 | + * Construct a logger with an open log file. | |
| 66 | + ***************************************************************************/ | |
| 67 | +GLog::GLog(const std::string& filename, bool clobber) | |
| 68 | +{ | |
| 69 | + // Initialise private members for clean destruction | |
| 70 | + init_members(); | |
| 71 | + | |
| 72 | + // Open file | |
| 73 | + open(filename, clobber); | |
| 74 | + | |
| 75 | + // Return | |
| 76 | + return; | |
| 77 | +} | |
| 78 | + | |
| 79 | + | |
| 80 | +/***********************************************************************//** | |
| 51 | 81 | * @brief Copy constructor |
| 52 | 82 | * |
| 53 | 83 | * @param[in] log Object from which the instance should be built. |
| ... | ... | @@ -110,12 +140,364 @@ GLog& GLog::operator= (const GLog& log) |
| 110 | 140 | } |
| 111 | 141 | |
| 112 | 142 | |
| 143 | +/**************************************************************************//** | |
| 144 | + * @brief Message logging operator | |
| 145 | + * | |
| 146 | + * @param[in] msgFormat Pointer to message format. | |
| 147 | + * @param[in] ... Message to put into log. | |
| 148 | + * | |
| 149 | + * This operator provides message logging capabilities in C style. It expects | |
| 150 | + * a C-style format string followed by an arbitrary number of arguments that | |
| 151 | + * is used to fill the format. | |
| 152 | + * | |
| 153 | + * @todo A static buffer of length 8192 is allocated. Although this is likely | |
| 154 | + * sufficient for any normal application there is nothing that prevents in | |
| 155 | + * principle the overflow of the buffer. A more sophisticated scheme should be | |
| 156 | + * implemented. | |
| 157 | + ******************************************************************************/ | |
| 158 | +void GLog::operator()(const char *msgFormat, ...) | |
| 159 | +{ | |
| 160 | + // Allocate message buffer | |
| 161 | + char buffer[8192]; | |
| 162 | + | |
| 163 | + // Put message into buffer | |
| 164 | + va_list vl; | |
| 165 | + va_start(vl, msgFormat); | |
| 166 | + vsprintf(buffer, msgFormat, vl); | |
| 167 | + va_end(vl); | |
| 168 | + | |
| 169 | + // Append message to string buffer | |
| 170 | + m_buffer.append(buffer); | |
| 171 | + m_buffer.append("\n"); | |
| 172 | + | |
| 173 | + // Flush buffer | |
| 174 | + flush(true); | |
| 175 | + | |
| 176 | + // Return | |
| 177 | + return; | |
| 178 | + | |
| 179 | +} | |
| 180 | + | |
| 181 | + | |
| 182 | +/***********************************************************************//** | |
| 183 | + * @brief Insert string into output stream | |
| 184 | + * | |
| 185 | + * @param[in] value String to be inserted. | |
| 186 | + ***************************************************************************/ | |
| 187 | +GLog& GLog::operator<<(const std::string& value) | |
| 188 | +{ | |
| 189 | + // Add string to buffer | |
| 190 | + m_buffer.append(value); | |
| 191 | + | |
| 192 | + // Flush buffer | |
| 193 | + flush(); | |
| 194 | + | |
| 195 | + // Return logger | |
| 196 | + return *this; | |
| 197 | +} | |
| 198 | + | |
| 199 | + | |
| 200 | +/***********************************************************************//** | |
| 201 | + * @brief Insert bool into output stream | |
| 202 | + * | |
| 203 | + * @param[in] value Boolean to be inserted. | |
| 204 | + ***************************************************************************/ | |
| 205 | +GLog& GLog::operator<<(const bool& value) | |
| 206 | +{ | |
| 207 | + // Add boolean to buffer | |
| 208 | + if (value) | |
| 209 | + m_buffer.append("true"); | |
| 210 | + else | |
| 211 | + m_buffer.append("false"); | |
| 212 | + | |
| 213 | + // Flush buffer | |
| 214 | + flush(); | |
| 215 | + | |
| 216 | + // Return logger | |
| 217 | + return *this; | |
| 218 | +} | |
| 219 | + | |
| 220 | + | |
| 221 | +/***********************************************************************//** | |
| 222 | + * @brief Insert integer into output stream | |
| 223 | + * | |
| 224 | + * @param[in] value Integer to be inserted. | |
| 225 | + ***************************************************************************/ | |
| 226 | +GLog& GLog::operator<<(const int& value) | |
| 227 | +{ | |
| 228 | + // Allocate output stream | |
| 229 | + std::ostringstream oss; | |
| 230 | + | |
| 231 | + // Put value into stream | |
| 232 | + oss << value; | |
| 233 | + | |
| 234 | + // Append stream to buffer | |
| 235 | + m_buffer.append(oss.str()); | |
| 236 | + | |
| 237 | + // Flush buffer | |
| 238 | + flush(); | |
| 239 | + | |
| 240 | + // Return logger | |
| 241 | + return *this; | |
| 242 | +} | |
| 243 | + | |
| 244 | + | |
| 245 | +/***********************************************************************//** | |
| 246 | + * @brief Insert double precision value into output stream | |
| 247 | + * | |
| 248 | + * @param[in] value Double precision value to be inserted. | |
| 249 | + ***************************************************************************/ | |
| 250 | +GLog& GLog::operator<<(const double& value) | |
| 251 | +{ | |
| 252 | + // Allocate output stream | |
| 253 | + std::ostringstream oss; | |
| 254 | + | |
| 255 | + // Put value into stream | |
| 256 | + oss << value; | |
| 257 | + | |
| 258 | + // Append stream to buffer | |
| 259 | + m_buffer.append(oss.str()); | |
| 260 | + | |
| 261 | + // Flush buffer | |
| 262 | + flush(); | |
| 263 | + | |
| 264 | + // Return logger | |
| 265 | + return *this; | |
| 266 | +} | |
| 267 | + | |
| 268 | + | |
| 269 | +/***********************************************************************//** | |
| 270 | + * @brief Insert character value into output stream | |
| 271 | + * | |
| 272 | + * @param[in] value Character value to be inserted. | |
| 273 | + ***************************************************************************/ | |
| 274 | +GLog& GLog::operator<<(const char& value) | |
| 275 | +{ | |
| 276 | + // Allocate output stream | |
| 277 | + std::ostringstream oss; | |
| 278 | + | |
| 279 | + // Put value into stream | |
| 280 | + oss << value; | |
| 281 | + | |
| 282 | + // Append stream to buffer | |
| 283 | + m_buffer.append(oss.str()); | |
| 284 | + | |
| 285 | + // Flush buffer | |
| 286 | + flush(); | |
| 287 | + | |
| 288 | + // Return logger | |
| 289 | + return *this; | |
| 290 | +} | |
| 291 | + | |
| 292 | + | |
| 293 | +/***********************************************************************//** | |
| 294 | + * @brief Ostream function output operator | |
| 295 | + * | |
| 296 | + * @param[in] fn Ostream function. | |
| 297 | + * | |
| 298 | + * The function output operator is interpreted as a line feed operator. | |
| 299 | + * | |
| 300 | + * @todo This is a quick an dirty implementation of the std::endl operator. | |
| 301 | + * A clean GLog::endl operator should be implemented instead, yet this needs | |
| 302 | + * some deeper understanding of our the | |
| 303 | + ***************************************************************************/ | |
| 304 | +GLog& GLog::operator<<(std::ostream& (*fn)(std::ostream&)) | |
| 305 | +{ | |
| 306 | + // Append CR to buffer | |
| 307 | + m_buffer.append("\n"); | |
| 308 | + | |
| 309 | + // Flush buffer | |
| 310 | + flush(true); | |
| 311 | + | |
| 312 | + // Return output stream | |
| 313 | + return *this; | |
| 314 | +} | |
| 315 | + | |
| 316 | + | |
| 113 | 317 | /*========================================================================== |
| 114 | 318 | = = |
| 115 | 319 | = Public methods = |
| 116 | 320 | = = |
| 117 | 321 | ==========================================================================*/ |
| 118 | 322 | |
| 323 | +/***********************************************************************//** | |
| 324 | + * @brief Clear object | |
| 325 | + ***************************************************************************/ | |
| 326 | +void GLog::clear(void) | |
| 327 | +{ | |
| 328 | + // Free members | |
| 329 | + free_members(); | |
| 330 | + | |
| 331 | + // Init members | |
| 332 | + init_members(); | |
| 333 | + | |
| 334 | + // Return | |
| 335 | + return; | |
| 336 | +} | |
| 337 | + | |
| 338 | + | |
| 339 | +/***********************************************************************//** | |
| 340 | + * @brief Return the number of characters that are actually in the buffer | |
| 341 | + ***************************************************************************/ | |
| 342 | +int GLog::size(void) const | |
| 343 | +{ | |
| 344 | + // Return | |
| 345 | + return m_buffer.size(); | |
| 346 | +} | |
| 347 | + | |
| 348 | + | |
| 349 | +/***********************************************************************//** | |
| 350 | + * @brief Open log file | |
| 351 | + * | |
| 352 | + * @param[in] filename Name of log file. | |
| 353 | + * @param[in] clobber If true overwrite any existing file, otherwise append. | |
| 354 | + * | |
| 355 | + * Opens a file for logging. If a log file was already open it is closed | |
| 356 | + * before opening a new file. | |
| 357 | + ***************************************************************************/ | |
| 358 | +void GLog::open(const std::string& filename, bool clobber) | |
| 359 | +{ | |
| 360 | + // Close any existing file | |
| 361 | + close(); | |
| 362 | + | |
| 363 | + // Open file | |
| 364 | + if (clobber) | |
| 365 | + m_file = fopen(filename.c_str(), "w"); | |
| 366 | + else | |
| 367 | + m_file = fopen(filename.c_str(), "a"); | |
| 368 | + | |
| 369 | + // Return | |
| 370 | + return; | |
| 371 | +} | |
| 372 | + | |
| 373 | + | |
| 374 | +/***********************************************************************//** | |
| 375 | + * @brief Close log file | |
| 376 | + * | |
| 377 | + * Close log file. This method even works if no file has been opened. In any | |
| 378 | + * case flushing of the buffer is enforced. | |
| 379 | + ***************************************************************************/ | |
| 380 | +void GLog::close(void) | |
| 381 | +{ | |
| 382 | + // Flush buffer | |
| 383 | + flush(true); | |
| 384 | + | |
| 385 | + // Close any open file | |
| 386 | + if (m_file != NULL) { | |
| 387 | + fclose(m_file); | |
| 388 | + m_file = NULL; | |
| 389 | + } | |
| 390 | + | |
| 391 | + // Return | |
| 392 | + return; | |
| 393 | +} | |
| 394 | + | |
| 395 | + | |
| 396 | +/***********************************************************************//** | |
| 397 | + * @brief Set data flag that controls date prefixing | |
| 398 | + * | |
| 399 | + * @param[in] flag Enable/disable date flag (true/false). | |
| 400 | + ***************************************************************************/ | |
| 401 | +void GLog::date(bool flag) | |
| 402 | +{ | |
| 403 | + // Set flag | |
| 404 | + m_use_date = flag; | |
| 405 | + | |
| 406 | + // Return | |
| 407 | + return; | |
| 408 | +} | |
| 409 | + | |
| 410 | + | |
| 411 | +/***********************************************************************//** | |
| 412 | + * @brief Enables/disables logging into standard output stream | |
| 413 | + * | |
| 414 | + * @param[in] flag Enable/disable logging (true/false). | |
| 415 | + * | |
| 416 | + * Enables or disables logging into the standard output stream. | |
| 417 | + ***************************************************************************/ | |
| 418 | +void GLog::cout(bool flag) | |
| 419 | +{ | |
| 420 | + // Set flag | |
| 421 | + m_stdout = flag; | |
| 422 | + | |
| 423 | + // Return | |
| 424 | + return; | |
| 425 | +} | |
| 426 | + | |
| 427 | + | |
| 428 | +/***********************************************************************//** | |
| 429 | + * @brief Enables/disables logging into standard error stream | |
| 430 | + * | |
| 431 | + * @param[in] flag Enable/disable logging (true/false). | |
| 432 | + * | |
| 433 | + * Enables or disables logging into the standard error stream. | |
| 434 | + ***************************************************************************/ | |
| 435 | +void GLog::cerr(bool flag) | |
| 436 | +{ | |
| 437 | + // Set flag | |
| 438 | + m_stderr = flag; | |
| 439 | + | |
| 440 | + // Return | |
| 441 | + return; | |
| 442 | +} | |
| 443 | + | |
| 444 | + | |
| 445 | +/***********************************************************************//** | |
| 446 | + * @brief Set name to put into prefix | |
| 447 | + * | |
| 448 | + * @param[in] name Name to put into prefix. | |
| 449 | + ***************************************************************************/ | |
| 450 | +void GLog::name(const std::string& name) | |
| 451 | +{ | |
| 452 | + // Set name | |
| 453 | + m_name = name; | |
| 454 | + | |
| 455 | + // Return | |
| 456 | + return; | |
| 457 | +} | |
| 458 | + | |
| 459 | + | |
| 460 | +/***********************************************************************//** | |
| 461 | + * @brief Set the maximum buffer size | |
| 462 | + * | |
| 463 | + * @param[in] size Maximum buffer size. | |
| 464 | + * | |
| 465 | + * Set the maximum number of characters allowed in the internal buffer before | |
| 466 | + * the buffer is flushed into the specified streams or file. | |
| 467 | + * | |
| 468 | + * @todo No maximum buffer size checking is performed. This could be | |
| 469 | + * implemented but is not really crucial since the physical buffer size can | |
| 470 | + * indeed be larger than this maximum size. | |
| 471 | + ***************************************************************************/ | |
| 472 | +void GLog::max_size(int size) | |
| 473 | +{ | |
| 474 | + // Set size | |
| 475 | + m_max_length = size; | |
| 476 | + | |
| 477 | + // Return | |
| 478 | + return; | |
| 479 | +} | |
| 480 | + | |
| 481 | + | |
| 482 | +/***********************************************************************//** | |
| 483 | + * @brief Set indentation | |
| 484 | + * | |
| 485 | + * @param[in] indent Indentation in number of characters. | |
| 486 | + * | |
| 487 | + * Set the indentation of the logger. This specifies the number of whitespace | |
| 488 | + * characters that is added between the prefix and the log message of each | |
| 489 | + * line. Indentation allows for easy formatting of text in the log file. | |
| 490 | + ***************************************************************************/ | |
| 491 | +void GLog::indent(int indent) | |
| 492 | +{ | |
| 493 | + // Set size | |
| 494 | + m_indent = indent; | |
| 495 | + | |
| 496 | + // Return | |
| 497 | + return; | |
| 498 | +} | |
| 499 | + | |
| 500 | + | |
| 119 | 501 | /*========================================================================== |
| 120 | 502 | = = |
| 121 | 503 | = Private methods = |
| ... | ... | @@ -128,6 +510,15 @@ GLog& GLog::operator= (const GLog& log) |
| 128 | 510 | void GLog::init_members(void) |
| 129 | 511 | { |
| 130 | 512 | // Initialise members |
| 513 | + m_max_length = 8192; | |
| 514 | + m_indent = 0; | |
| 515 | + m_stdout = false; | |
| 516 | + m_stderr = false; | |
| 517 | + m_use_date = false; | |
| 518 | + m_newline = true; | |
| 519 | + m_file = NULL; | |
| 520 | + m_name.clear(); | |
| 521 | + m_buffer.clear(); | |
| 131 | 522 | |
| 132 | 523 | // Return |
| 133 | 524 | return; |
| ... | ... | @@ -142,6 +533,15 @@ void GLog::init_members(void) |
| 142 | 533 | void GLog::copy_members(const GLog& log) |
| 143 | 534 | { |
| 144 | 535 | // Copy attributes |
| 536 | + m_max_length = log.m_max_length; | |
| 537 | + m_indent = log.m_indent; | |
| 538 | + m_stdout = log.m_stdout; | |
| 539 | + m_stderr = log.m_stderr; | |
| 540 | + m_use_date = log.m_use_date; | |
| 541 | + m_newline = log.m_newline; | |
| 542 | + m_name = log.m_name; | |
| 543 | + m_buffer = log.m_buffer; | |
| 544 | + m_file = log.m_file; | |
| 145 | 545 | |
| 146 | 546 | // Return |
| 147 | 547 | return; |
| ... | ... | @@ -150,33 +550,180 @@ void GLog::copy_members(const GLog& log) |
| 150 | 550 | |
| 151 | 551 | /***********************************************************************//** |
| 152 | 552 | * @brief Delete class members |
| 553 | + * | |
| 554 | + * Deletes class member after flushing the buffer and closing the log file. | |
| 153 | 555 | ***************************************************************************/ |
| 154 | 556 | void GLog::free_members(void) |
| 155 | 557 | { |
| 558 | + // Flush buffer | |
| 559 | + flush(true); | |
| 560 | + | |
| 561 | + // Close log file | |
| 562 | + close(); | |
| 563 | + | |
| 156 | 564 | // Return |
| 157 | 565 | return; |
| 158 | 566 | } |
| 159 | 567 | |
| 160 | 568 | |
| 161 | -/*========================================================================== | |
| 162 | - = = | |
| 163 | - = Friends = | |
| 164 | - = = | |
| 165 | - ==========================================================================*/ | |
| 569 | +/***********************************************************************//** | |
| 570 | + * @brief Flush string buffer into log file | |
| 571 | + * | |
| 572 | + * @param[in] force If true, force flushing. | |
| 573 | + * | |
| 574 | + * Flush string buffer if it is full or if flushing is enforced. This method | |
| 575 | + * writes the output string in the relevant streams. It decomposes the | |
| 576 | + * buffer in lines that a separated by a '\n' character and preprends, if | |
| 577 | + * requested, the current date and name. The following streams are currently | |
| 578 | + * implemented (and will be filled in parallel): stdout, stderr, and an ASCII | |
| 579 | + * file. | |
| 580 | + ***************************************************************************/ | |
| 581 | +void GLog::flush(bool force) | |
| 582 | +{ | |
| 583 | + // Check if buffer should be flushed | |
| 584 | + bool flush = (force || size() > m_max_length); | |
| 585 | + | |
| 586 | + // Flush buffer | |
| 587 | + if (flush) { | |
| 588 | + | |
| 589 | + // Flush buffer until it is empty | |
| 590 | + while (m_buffer.size() > 0) { | |
| 591 | + | |
| 592 | + // Initialise newline for next line | |
| 593 | + bool newline = m_newline; | |
| 594 | + | |
| 595 | + // Find next CR | |
| 596 | + std::string line; | |
| 597 | + size_t pos = m_buffer.find_first_of("\n", 0); | |
| 598 | + if (pos == std::string::npos) { | |
| 599 | + line = m_buffer; | |
| 600 | + newline = false; | |
| 601 | + m_buffer.clear(); | |
| 602 | + } | |
| 603 | + else { | |
| 604 | + line = m_buffer.substr(0, pos) + "\n"; | |
| 605 | + m_buffer = m_buffer.substr(pos+1, m_buffer.size()-pos); | |
| 606 | + newline = true; | |
| 607 | + } | |
| 608 | + | |
| 609 | + // Prepend prefix if we are at the beginning of a new line | |
| 610 | + if (m_newline) { | |
| 611 | + std::string prefix = ""; | |
| 612 | + if (m_use_date) | |
| 613 | + prefix.append(strdate()); | |
| 614 | + if (m_name.length() > 0) | |
| 615 | + prefix.append(" "+m_name); | |
| 616 | + if (prefix.length() > 0) | |
| 617 | + prefix.append(": "); | |
| 618 | + line = prefix + fill(" ", m_indent) + line; | |
| 619 | + } | |
| 620 | + | |
| 621 | + // Put line into requested streams | |
| 622 | + if (m_stdout) | |
| 623 | + std::cout << line; | |
| 624 | + if (m_stderr) | |
| 625 | + std::cerr << line; | |
| 626 | + if (m_file != NULL) | |
| 627 | + fprintf(m_file, line.c_str()); | |
| 628 | + | |
| 629 | + // Set newline flag for next line | |
| 630 | + m_newline = newline; | |
| 631 | + | |
| 632 | + } // endwhile: flush until empty | |
| 633 | + | |
| 634 | + } // endif: flush was required | |
| 635 | + | |
| 636 | + // Return | |
| 637 | + return; | |
| 638 | +} | |
| 639 | + | |
| 166 | 640 | |
| 167 | 641 | /***********************************************************************//** |
| 168 | - * @brief Put object in output stream | |
| 642 | + * @brief Write string as header into logger | |
| 643 | + * | |
| 644 | + * @param[in] arg Header string. | |
| 645 | + * @param[in] level Header level (0,1,...). | |
| 169 | 646 | * |
| 170 | - * @param[in] os Output stream into which the model will be dumped | |
| 171 | - * @param[in] log Object to be dumped | |
| 647 | + * Writes a string as header into the logger. Various header levels exist: | |
| 648 | + * 0: 80 character wide centred header | |
| 649 | + * 1: Header framed by '=' characters | |
| 650 | + * 2: Header framed by '-' characters | |
| 172 | 651 | ***************************************************************************/ |
| 173 | -std::ostream& operator<< (std::ostream& os, const GLog& log) | |
| 652 | +void GLog::header(const std::string& arg, int level) | |
| 174 | 653 | { |
| 175 | - // Put object in stream | |
| 176 | - os << "=== GLog ===" << std::endl; | |
| 654 | + // Declare frame and text strings | |
| 655 | + std::string frame; | |
| 656 | + std::string text; | |
| 657 | + | |
| 658 | + // Create level dependent header strings | |
| 659 | + switch (level) { | |
| 660 | + case 0: | |
| 661 | + break; | |
| 662 | + case 1: | |
| 663 | + case 2: | |
| 664 | + text = "| " + arg + " |"; | |
| 665 | + frame = (level == 1) ? "+" + fill("=", text.length()-2) + "+" | |
| 666 | + : "+" + fill("-", text.length()-2) + "+"; | |
| 667 | + break; | |
| 668 | + default: | |
| 669 | + break; | |
| 670 | + } | |
| 671 | + | |
| 672 | + // Write header into logger | |
| 673 | + if (text.length() > 0) { | |
| 674 | + m_buffer.append(frame); | |
| 675 | + m_buffer.append("\n"); | |
| 676 | + m_buffer.append(text); | |
| 677 | + m_buffer.append("\n"); | |
| 678 | + m_buffer.append(frame); | |
| 679 | + m_buffer.append("\n"); | |
| 680 | + flush(true); | |
| 681 | + } | |
| 177 | 682 | |
| 178 | - // Return output stream | |
| 179 | - return os; | |
| 683 | + // Return | |
| 684 | + return; | |
| 685 | +} | |
| 686 | + | |
| 687 | + | |
| 688 | +/***********************************************************************//** | |
| 689 | + * @brief Return current date | |
| 690 | + * | |
| 691 | + * Returns the current date as string in the format yyyy-mm-ddThh:mm:ss. | |
| 692 | + ***************************************************************************/ | |
| 693 | +std::string GLog::strdate(void) | |
| 694 | +{ | |
| 695 | + // Allocate variables | |
| 696 | + struct tm timeStruct; | |
| 697 | + time_t now; | |
| 698 | + char buffer[100]; | |
| 699 | + | |
| 700 | + // Get time | |
| 701 | + now = time(NULL); | |
| 702 | + #ifdef HAVE_GMTIME_R | |
| 703 | + gmtime_r(&now, &timeStruct); | |
| 704 | + #else | |
| 705 | + memcpy(&timeStruct, gmtime(&now), sizeof(struct tm)); | |
| 706 | + #endif | |
| 707 | + | |
| 708 | + // Write message type, time and task name to buffer | |
| 709 | + sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d", | |
| 710 | + timeStruct.tm_year + 1900, | |
| 711 | + timeStruct.tm_mon + 1, | |
| 712 | + timeStruct.tm_mday, | |
| 713 | + timeStruct.tm_hour, | |
| 714 | + timeStruct.tm_min, | |
| 715 | + timeStruct.tm_sec); | |
| 716 | + | |
| 717 | + // Build string from buffer | |
| 718 | + std::string date = buffer; | |
| 719 | + | |
| 720 | + // Return date | |
| 721 | + return date; | |
| 180 | 722 | } |
| 181 | 723 | |
| 182 | 724 | |
| 725 | +/*========================================================================== | |
| 726 | + = = | |
| 727 | + = Friends = | |
| 728 | + = = | |
| 729 | + ==========================================================================*/ | ... | ... |