38 #include "blocxx/BLOCXX_config.h" 54 #ifdef BLOCXX_HAVE_UNISTD_H 68 namespace LogMessagePatternFormatterImpl
95 using namespace LogMessagePatternFormatterImpl;
114 convert(message, output);
119 convert(message, buf);
123 if (m_formatting.minWidth > 0)
125 output.
append(&(std::vector<char>(
size_t(m_formatting.minWidth),
' ')[0]), m_formatting.minWidth);
131 if (len > m_formatting.maxWidth)
135 buf.
truncate(m_formatting.maxWidth);
143 else if (len < m_formatting.minWidth)
148 output.
append(&(std::vector<char>(
size_t(m_formatting.minWidth - len),
' ')[0]), m_formatting.minWidth - len);
152 output.
append(&(std::vector<char>(
size_t(m_formatting.minWidth - len),
' ')[0]), m_formatting.minWidth - len);
183 iter_t end(m_patternConverters.end());
184 for (iter_t
i(m_patternConverters.begin());
i != end; ++
i)
186 (*i)->formatMessage(message, output);
198 class MessageConverter :
public Converter
205 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 207 output += message.message;
211 #define CDATA_START_DEF "<![CDATA[" 212 #define CDATA_END_DEF "]]>" 213 #define CDATA_PSEUDO_END_DEF "]]>" 221 class XMLMessageConverter :
public Converter
224 XMLMessageConverter(
const Formatting&
formatting)
228 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 230 output += CDATA_START;
231 const String& msg(message.message);
234 size_t end = msg.indexOf(CDATA_END);
243 output.append(&msg[start], end - start);
244 output += CDATA_EMBEDDED_END;
245 start = end + static_cast<String>(CDATA_END).length();
246 if (start < msg.length())
248 end = msg.indexOf(CDATA_END, start);
261 class LiteralConverter :
public Converter
264 LiteralConverter(
const String&
literal)
268 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 278 class ThreadConverter :
public Converter
285 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 292 class PidConverter :
public Converter
299 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 302 output += ::GetCurrentProcessId();
304 output += ::getpid();
310 class ComponentConverter :
public Converter
313 ComponentConverter(
const Formatting&
formatting,
int precision)
318 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 322 output += message.component;
326 const String& component(message.component);
327 size_t len(component.length());
331 end = component.lastIndexOf(
'.', end - 1);
338 output += component.substring(end + 1, len - (end + 1));
347 class FileLocationConverter :
public Converter
350 FileLocationConverter(
const Formatting&
formatting)
354 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 356 if (message.filename != 0)
358 output += message.filename;
364 class FullLocationConverter :
public Converter
367 FullLocationConverter(
const Formatting&
formatting)
371 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 373 if (message.filename != 0)
375 output += message.filename;
377 output += message.fileline;
384 class LineLocationConverter :
public Converter
387 LineLocationConverter(
const Formatting&
formatting)
391 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 393 output += message.fileline;
398 class MethodLocationConverter :
public Converter
401 MethodLocationConverter(
const Formatting&
formatting)
405 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 407 if (message.methodname != 0)
409 output += message.methodname;
415 class CategoryConverter :
public Converter
418 CategoryConverter(
const Formatting&
formatting)
422 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 424 output += message.category;
429 class RelativeTimeConverter :
public Converter
432 RelativeTimeConverter(
const Formatting&
formatting)
436 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 438 output += getRelativeTime();
442 static UInt64 getRelativeTime()
449 static UInt64 getNowMillis()
453 return UInt64(now.get()) * 1000 + (now.getMicrosecond() / 1000);
470 class DateConverter :
public Converter
477 size_t pos =
m_format.indexOf(
"%Q");
485 virtual void convert(
const LogMessage &message, StringBuffer &output)
const 494 size_t len = ::strftime(buf,
sizeof(buf),
m_format.c_str(), &nowTm);
499 char* p = strstr(buf,
"%Q");
504 long deciMillis = now.getMicrosecond() / 1000;
505 String strMillis(deciMillis);
507 switch (strMillis.length())
545 Parser(
const String& pattern_)
547 ,
state(E_LITERAL_STATE)
552 void parse(Array<ConverterRef>& converters)
555 size_t patternLength(
pattern.length());
557 while (
i < patternLength)
563 case E_LITERAL_STATE:
565 if (
i == patternLength)
586 converters.push_back(ConverterRef(
new LiteralConverter(
literal.toString())));
590 state = E_CONVERTER_STATE;
621 if (
i + 1 > patternLength)
631 int hexNumber = std::strtol(begin, &end, 16);
632 if (end == begin || errno == ERANGE || hexNumber > CHAR_MAX)
638 literal += static_cast<char>(hexNumber);
639 i += (end - begin) + 1;
655 case E_CONVERTER_STATE:
674 converters.push_back(finalizeConverter(c));
692 converters.push_back(finalizeConverter(c));
707 Format(
"Invalid pattern \"%1\" in position %2. Was expecting a digit, instead got char %3.",
722 converters.push_back(finalizeConverter(c));
723 state = E_LITERAL_STATE;
733 converters.push_back(ConverterRef(
new LiteralConverter(
literal.toString())));
743 size_t end =
pattern.indexOf(
'}',
i);
746 String rv =
pattern.substring(
i + 1, end - (
i + 1));
759 String opt = getOption();
767 catch (StringConversionException& e)
770 Format(
"Invalid pattern \"%1\" in position %2. A positive integer is required for precision option (%3).",
779 ConverterRef finalizeConverter(
char c)
787 rv =
new ComponentConverter(
formatting, getPrecision());
794 String dateOpt = getOption();
801 dateFormat = dateOpt;
818 rv =
new DateConverter(
formatting, dateFormat);
881 #if 0 // don't support these for now. 897 Format(
"Invalid pattern \"%1\" in position %2. Unsupported conversion (%3).",
906 state = E_LITERAL_STATE;
926 parser.parse(m_patternConverters);
String substring(size_t beginIndex, size_t length=npos) const
Create another String object that is comprised of a substring of this String object.
#define BLOCXX_THROW_ERR(exType, msg, err)
Throw an exception using FILE and LINE.
This String class is an abstract data type that represents as NULL terminated string of characters.
BLOCXX_COMMON_API UInt64 thread_t_ToUInt64(Thread_t thr)
Convert a Thread_t to an UInt64.
LazyGlobal< String, char const *const > GlobalString
#define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
void truncate(size_t index)
Truncate the string at the given index.
#define BLOCXX_GLOBAL_STRING_INIT(str)
V::const_iterator const_iterator
StringBuffer & append(char c)
This class can be used to store a global variable that is lazily initialized in a thread safe manner.