File: DefaultFormatter.cpp

package info (click to toggle)
spring 88.0%2Bdfsg1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 41,524 kB
  • sloc: cpp: 343,114; ansic: 38,414; python: 12,257; java: 12,203; awk: 5,748; sh: 1,204; xml: 997; perl: 405; objc: 192; makefile: 181; php: 134; sed: 2
file content (157 lines) | stat: -rwxr-xr-x 4,353 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

/**
 * This is the default formatter for the ILog.h logging API.
 * It formats the message and eventually adds a prefix.
 * The prefix will usually consist of the level, section and possibly a
 * timestamp.
 */

#include "LogUtil.h"
#include "Level.h"
#include "Section.h"
#include "System/maindefines.h"
#include "System/SafeCStrings.h"

#include <cstdio>
#include <cstdarg>
#include <cstring>


#ifdef __cplusplus
extern "C" {
#endif

#ifdef _MSC_VER
#define va_copy(dst, src) ((dst) = (src))
#endif

static const int SECTION_SIZE_MIN = 10;
static const int SECTION_SIZE_MAX = 20;

// *******************************************************************************************
// Helpers
static inline void ResizeBuffer(char** buffer, size_t* bufferSize, const bool copy = false)
{
	*bufferSize <<= 2; // `2` to increase it faster
	char* old = *buffer;
	*buffer = new char[*bufferSize];
	if (copy) {
		memcpy(*buffer, old, *bufferSize >> 2);
	}
	delete[] old;
}


static inline void PrintfAppend(char** buffer, size_t* bufferSize, const char* fmt, va_list arguments)
{
	// dynamically adjust the buffer size until VSNPRINTF returns fine
	size_t bufferPos = strlen(*buffer);

	do {
		size_t freeBufferSize = (*bufferSize) - bufferPos;
		char* bufAppendPos = &((*buffer)[bufferPos]);

		// printf will move the internal pointer of va_list.
		// So we need to make a copy, if want to run it again.
		va_list arguments_;
		va_copy(arguments_, arguments); 
			VSNPRINTF(bufAppendPos, freeBufferSize, fmt, arguments_);
		va_end(arguments_);
		const bool bufferTooSmall = ((strlen(*buffer) + 1) >= *bufferSize);
		if (!bufferTooSmall) break;

		ResizeBuffer(buffer, bufferSize, true);
	} while (true);
}


// *******************************************************************************************

static void log_formatter_createPrefix_xorgStyle(char** buffer,
		size_t* bufferSize, const char* section, int level)
{
	section = log_util_prepareSection(section);

	const char levelChar = log_util_levelToChar(level);

	SNPRINTF(*buffer, *bufferSize, "(%c%c) %*.*s - ", levelChar, levelChar,
			SECTION_SIZE_MIN, SECTION_SIZE_MAX, section);
}


static void log_formatter_createPrefix_testing(char** buffer,
		size_t* bufferSize, const char* section, int level)
{
	section = log_util_prepareSection(section);

	const char* levelStr = log_util_levelToString(level);

	SNPRINTF(*buffer, *bufferSize, "%s %s: ", levelStr, section);
}


static void log_formatter_createPrefix_default(char** buffer,
		size_t* bufferSize, const char* section, int level)
{
	(*buffer)[0] = '\0';

	if (!LOG_SECTION_IS_DEFAULT(section)) {
		section = log_util_prepareSection(section);
		STRCAT_T(*buffer, *bufferSize, "[");
		STRCAT_T(*buffer, *bufferSize, section);
		STRCAT_T(*buffer, *bufferSize, "] ");
	}
	if (level != LOG_LEVEL_INFO) {
		const char* levelStr = log_util_levelToString(level);
		STRCAT_T(*buffer, *bufferSize, levelStr);
		STRCAT_T(*buffer, *bufferSize, ": ");
	}
}


static inline void log_formatter_createPrefix(char** buffer, size_t* bufferSize,
		const char* section, int level)
{
	//log_formatter_createPrefix_xorgStyle(buffer, bufferSize, section, level);
	//log_formatter_createPrefix_testing(buffer, bufferSize, section, level);
	log_formatter_createPrefix_default(buffer, bufferSize, section, level);

	// check if the buffer was large enough, if not resize it and try again
	const bool bufferTooSmall = ((strlen(*buffer) + 1) >= *bufferSize);
	if (bufferTooSmall) {
		ResizeBuffer(buffer, bufferSize);
		log_formatter_createPrefix(buffer, bufferSize, section, level); // recursive
	}
}

// *******************************************************************************************

/**
 * @name logging_formatter
 * ILog.h formatter implementation.
 */
///@{

/**
 * Formats a log entry into its final string form.
 * @return a string buffer, allocated with new[] -> you have to delete[] it
 */
char* log_formatter_format(const char* section, int level, const char* fmt, va_list arguments)
{
	size_t bufferSize = 256;
	char* mem = new char[bufferSize];
	char** buffer = &mem;

	log_formatter_createPrefix(buffer, &bufferSize, section, level);
	PrintfAppend(buffer, &bufferSize, fmt, arguments);

	return *buffer;
}

///@}

#ifdef __cplusplus
} // extern "C"
#endif