PatternLayout.cpp
Go to the documentation of this file.
1 /*
2  * PatternLayout.cpp
3  *
4  * Copyright 2002, Bastiaan Bakker. All rights reserved.
5  *
6  * See the COPYING file for the terms of usage and distribution.
7  */
8 
9 #include "PortabilityImpl.hh"
10 
11 #include <log4cpp/PatternLayout.hh>
12 #include <log4cpp/Priority.hh>
13 #include <log4cpp/NDC.hh>
14 #include <log4cpp/TimeStamp.hh>
15 #include <log4cpp/FactoryParams.hh>
16 #include <memory>
17 #include <stdlib.h>
18 
19 #ifdef LOG4CPP_HAVE_SSTREAM
20 #include <sstream>
21 #else
22 #include <strstream>
23 #endif
24 
25 #include <iomanip>
26 #include <ctime>
27 #include <cstdlib>
28 #include "Localtime.hh"
29 
30 #ifdef LOG4CPP_HAVE_INT64_T
31 #ifdef LOG4CPP_HAVE_STDINT_H
32 #include <stdint.h>
33 #endif // LOG4CPP_HAVE_STDINT_H
34 
35 #ifdef LOG4CPP_MISSING_INT64_OSTREAM_OP
36 /* workaround suggested at:
37  http://support.microsoft.com/default.aspx?scid=kb;EN-US;q168440
38 */
39 
40 #include <stdio.h>
41 
42 std::ostream& operator<<(std::ostream& os, int64_t i) {
43  char buf[20];
44  ::sprintf(buf,"%I64d", i);
45  return os << buf;
46 }
47 #endif // LOG4CPP_MISSING_INT64_OSTREAM_OP
48 #endif // LOG4CPP_HAVE_INT64_T
49 
50 namespace log4cpp {
51 
53  StringLiteralComponent(const std::string& literal) :
54  _literal(literal) {
55  }
56 
57  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
58  out << _literal;
59  }
60 
61  private:
62  std::string _literal;
63  };
64 
66  CategoryNameComponent(std::string specifier) {
67  if (specifier == "") {
68  _precision = -1;
69  } else {
70 #ifdef LOG4CPP_HAVE_SSTREAM
71  std::istringstream s(specifier);
72 #else
73  std::istrstream s(specifier.c_str());
74 #endif
75  s >> _precision;
76  }
77  }
78 
79  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
80  if (_precision == -1) {
81  out << event.categoryName;
82  } else {
83  std::string::size_type begin = std::string::npos;
84  for(int i = 0; i < _precision; i++) {
85  begin = event.categoryName.rfind('.', begin - 2);
86  if (begin == std::string::npos) {
87  begin = 0;
88  break;
89  }
90  begin++;
91  }
92  out << event.categoryName.substr(begin);
93  }
94  }
95 
96  private:
98  };
99 
101  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
102  out << event.message;
103  }
104  };
105 
107  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
108  out << event.ndc;
109  }
110  };
111 
113  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
114  out << Priority::getPriorityName(event.priority);
115  }
116  };
117 
119  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
120  out << event.threadName;
121  }
122  };
123 
125  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
126  out << std::clock();
127  }
128  };
129 
131  static const char* const FORMAT_ISO8601;
132  static const char* const FORMAT_ABSOLUTE;
133  static const char* const FORMAT_DATE;
134 
135  TimeStampComponent(std::string timeFormat) {
136  if ((timeFormat == "") || (timeFormat == "ISO8601")) {
137  timeFormat = FORMAT_ISO8601;
138  } else if (timeFormat == "ABSOLUTE") {
139  timeFormat = FORMAT_ABSOLUTE;
140  } else if (timeFormat == "DATE") {
141  timeFormat = FORMAT_DATE;
142  }
143  // want milliseconds?
144  std::string::size_type pos = timeFormat.find("%l");
145  if (pos == std::string::npos) {
146 
147  // want microseconds?
148  std::string::size_type pos = timeFormat.find("%L");
149  if (pos == std::string::npos) {
150  _printMillis = false;
151  _printMicros = false;
152  _timeFormat1 = timeFormat;
153  } else {
154  _printMillis = false;
155  _printMicros = true;
156  _timeFormat1 = timeFormat.substr(0, pos);
157  _timeFormat2 = timeFormat.substr(pos + 2);
158  }
159 
160  } else {
161  _printMillis = true;
162  _printMicros = false;
163  _timeFormat1 = timeFormat.substr(0, pos);
164  _timeFormat2 = timeFormat.substr(pos + 2);
165  }
166  }
167 
168  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
169  struct std::tm currentTime;
170  std::time_t t = event.timeStamp.getSeconds();
171  localtime(&t, &currentTime);
172  char formatted[103];
173  std::string timeFormat;
174  if (_printMillis) {
175  std::ostringstream formatStream;
176  formatStream << _timeFormat1
177  << std::setw(3) << std::setfill('0')
178  << event.timeStamp.getMilliSeconds()
179  << _timeFormat2;
180  timeFormat = formatStream.str();
181  } else if (_printMicros) {
182  std::ostringstream formatStream;
183  formatStream << _timeFormat1
184  << std::setw(6) << std::setfill('0')
185  << event.timeStamp.getMicroSeconds()
186  << _timeFormat2;
187  timeFormat = formatStream.str();
188  } else {
189  timeFormat = _timeFormat1;
190  }
191  std::strftime(formatted, sizeof(formatted), timeFormat.c_str(), &currentTime);
192  out << formatted;
193  }
194 
195  private:
196  std::string _timeFormat1;
197  std::string _timeFormat2;
200  };
201 
202  const char* const TimeStampComponent::FORMAT_ISO8601 = "%Y-%m-%d %H:%M:%S,%l";
203  const char* const TimeStampComponent::FORMAT_ABSOLUTE = "%H:%M:%S,%l";
204  const char* const TimeStampComponent::FORMAT_DATE = "%d %b %Y %H:%M:%S,%l";
205 
207  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
208  out << event.timeStamp.getSeconds();
209  }
210  };
211 
213  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
214 #ifdef LOG4CPP_HAVE_INT64_T
215  int64_t t = event.timeStamp.getSeconds() -
217  t *= 1000;
218  t += event.timeStamp.getMilliSeconds() -
220 
221  out << t;
222 #else
223  double t = event.timeStamp.getSeconds() -
225  t *= 1000;
226  t += event.timeStamp.getMilliSeconds() -
228 
229  out << std::setiosflags(std::ios::fixed)
230  << std::setprecision(0) << t;
231 #endif
232  }
233  };
234 
237  size_t minWidth, size_t maxWidth, bool alignLeft) :
238  _component(component) ,
239  _minWidth(minWidth),
240  _maxWidth(maxWidth),
241  _alignLeft(alignLeft) {
242  }
243 
245  delete _component;
246  }
247 
248  virtual void append(std::ostringstream& out, const LoggingEvent& event) {
250  _component->append(s, event);
251  std::string msg = s.str();
252  if (_maxWidth > 0 && _maxWidth < msg.length()) {
253  msg.erase(_maxWidth);
254  }
255  size_t fillCount = _minWidth - msg.length();
256  if (_minWidth > msg.length()) {
257  if (_alignLeft) {
258  out << msg << std::string(fillCount, ' ');
259  } else {
260  out << std::string(fillCount, ' ') << msg;
261  }
262  } else {
263  out << msg;
264  }
265  }
266 
267  private:
269  size_t _minWidth;
270  size_t _maxWidth;
272  };
273 
274  const char* PatternLayout::DEFAULT_CONVERSION_PATTERN = "%m%n";
275  const char* PatternLayout::SIMPLE_CONVERSION_PATTERN = "%p - %m%n";
276  const char* PatternLayout::BASIC_CONVERSION_PATTERN = "%R %p %c %x: %m%n";
277  const char* PatternLayout::TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %x - %m%n";
278 
280  try {
281  setConversionPattern(DEFAULT_CONVERSION_PATTERN);
282  } catch(ConfigureFailure&) {
283  }
284  }
285 
287  clearConversionPattern();
288  }
289 
291  for(ComponentVector::const_iterator i = _components.begin();
292  i != _components.end(); ++i) {
293  delete (*i);
294  }
295  _components.clear();
296  _conversionPattern = "";
297  }
298 
299  void PatternLayout::setConversionPattern(const std::string& conversionPattern) throw(ConfigureFailure) {
300 #ifdef LOG4CPP_HAVE_SSTREAM
301  std::istringstream conversionStream(conversionPattern);
302 #else
303  std::istrstream conversionStream(conversionPattern.c_str());
304 #endif
305  std::string literal;
306 
307  char ch;
308  PatternLayout::PatternComponent* component = NULL;
309  int minWidth = 0;
310  size_t maxWidth = 0;
311  clearConversionPattern();
312  while (conversionStream.get(ch)) {
313  if (ch == '%') {
314  // readPrefix;
315  {
316  char ch2;
317  conversionStream.get(ch2);
318  if ((ch2 == '-') || ((ch2 >= '0') && (ch2 <= '9'))) {
319  conversionStream.putback(ch2);
320  conversionStream >> minWidth;
321  conversionStream.get(ch2);
322  }
323  if (ch2 == '.') {
324  conversionStream >> maxWidth;
325  } else {
326  conversionStream.putback(ch2);
327  }
328  }
329  if (!conversionStream.get(ch)) {
330  std::ostringstream msg;
331  msg << "unterminated conversion specifier in '" << conversionPattern << "' at index " << conversionStream.tellg();
332  throw ConfigureFailure(msg.str());
333  }
334  std::string specPostfix = "";
335  // read postfix
336  {
337  char ch2;
338  if (conversionStream.get(ch2)) {
339  if (ch2 == '{') {
340  while(conversionStream.get(ch2) && (ch2 != '}'))
341  specPostfix += ch2;
342  } else {
343  conversionStream.putback(ch2);
344  }
345  }
346  }
347  switch (ch) {
348  case '%':
349  literal += ch;
350  break;
351  case 'm':
352  component = new MessageComponent();
353  break;
354  case 'n':
355  {
356  std::ostringstream endline;
357  endline << std::endl;
358  literal += endline.str();
359  }
360  break;
361  case 'c':
362  component = new CategoryNameComponent(specPostfix);
363  break;
364  case 'd':
365  component = new TimeStampComponent(specPostfix);
366  break;
367  case 'p':
368  component = new PriorityComponent();
369  break;
370  case 'r':
371  component = new MillisSinceEpochComponent();
372  break;
373  case 'R':
374  component = new SecondsSinceEpochComponent();
375  break;
376  case 't':
377  component = new ThreadNameComponent();
378  break;
379  case 'u':
380  component = new ProcessorTimeComponent();
381  break;
382  case 'x':
383  component = new NDCComponent();
384  break;
385  default:
386  std::ostringstream msg;
387  msg << "unknown conversion specifier '" << ch << "' in '" << conversionPattern << "' at index " << conversionStream.tellg();
388  throw ConfigureFailure(msg.str());
389  }
390  if (component) {
391  if (!literal.empty()) {
392  _components.push_back(new StringLiteralComponent(literal));
393  literal = "";
394  }
395  if ((minWidth != 0) || (maxWidth != 0)) {
396  component = new FormatModifierComponent(component, ::abs(minWidth), maxWidth, minWidth < 0);
397  minWidth = maxWidth = 0;
398  }
399  _components.push_back(component);
400  component = NULL;
401  }
402  } else {
403  literal += ch;
404  }
405  }
406  if (!literal.empty()) {
407  _components.push_back(new StringLiteralComponent(literal));
408  }
409 
410  _conversionPattern = conversionPattern;
411  }
412 
414  return _conversionPattern;
415  }
416 
417  std::string PatternLayout::format(const LoggingEvent& event) {
418  std::ostringstream message;
419 
420  for(ComponentVector::const_iterator i = _components.begin();
421  i != _components.end(); ++i) {
422  (*i)->append(message, event);
423  }
424 
425  return message.str();
426  }
427 
428  std::auto_ptr<Layout> create_pattern_layout(const FactoryParams& params)
429  {
430  std::string pattern;
431  params.get_for("pattern layout").optional("pattern", pattern);
432  std::auto_ptr<Layout> result(new PatternLayout);
433  PatternLayout* l = static_cast<PatternLayout*>(result.get());
434  if (pattern.empty() || pattern == "default")
435  return result;
436 
437  if (pattern == "simple")
438  {
439  l->setConversionPattern(PatternLayout::SIMPLE_CONVERSION_PATTERN);
440  return result;
441  }
442 
443  if (pattern == "basic")
444  {
445  l->setConversionPattern(PatternLayout::BASIC_CONVERSION_PATTERN);
446  return result;
447  }
448 
449  if (pattern == "ttcc")
450  {
451  l->setConversionPattern(PatternLayout::TTCC_CONVERSION_PATTERN);
452  return result;
453  }
454 
455  l->setConversionPattern(pattern);
456  return result;
457  }
458 }
optional_params_validator optional(const char *param, T &value) const
int getMilliSeconds() const
Definition: TimeStamp.hh:44
virtual void clearConversionPattern()
ostream & operator<<(ostream &os, const width &w)
Definition: Manipulator.cpp:10
static const char * DEFAULT_CONVERSION_PATTERN
virtual void append(std::ostringstream &out, const LoggingEvent &event)
virtual void append(std::ostringstream &out, const LoggingEvent &event)
CategoryNameComponent(std::string specifier)
PatternLayout::PatternComponent * _component
__int64 int64_t
Definition: config-win32.h:27
void localtime(const ::time_t *time,::tm *t)
Definition: Localtime.cpp:30
static const char *const FORMAT_DATE
virtual std::string format(const LoggingEvent &event)
virtual void append(std::ostringstream &out, const LoggingEvent &event)
virtual void setConversionPattern(const std::string &conversionPattern)
static const TimeStamp & getStartTime()
Definition: TimeStamp.hh:61
virtual void append(std::ostringstream &out, const LoggingEvent &event)
Priority::Value priority
Definition: LoggingEvent.hh:67
virtual void append(std::ostringstream &out, const LoggingEvent &event)
int getSeconds() const
Definition: TimeStamp.hh:36
static const char *const FORMAT_ISO8601
static const char * SIMPLE_CONVERSION_PATTERN
virtual void append(std::ostringstream &out, const LoggingEvent &event)
StringLiteralComponent(const std::string &literal)
static const char * BASIC_CONVERSION_PATTERN
FormatModifierComponent(PatternLayout::PatternComponent *component, size_t minWidth, size_t maxWidth, bool alignLeft)
static const char * TTCC_CONVERSION_PATTERN
virtual void append(std::ostringstream &out, const LoggingEvent &event)
virtual void append(std::ostringstream &out, const LoggingEvent &event)
virtual std::string getConversionPattern() const
virtual void append(std::ostringstream &out, const LoggingEvent &event)
static const char *const FORMAT_ABSOLUTE
details::parameter_validator get_for(const char *tag) const
std::auto_ptr< Layout > create_pattern_layout(const FactoryParams &params)
virtual void append(std::ostringstream &out, const LoggingEvent &event)
static const std::string & getPriorityName(int priority)
Definition: Priority.cpp:37
virtual void append(std::ostringstream &out, const LoggingEvent &event)
TimeStampComponent(std::string timeFormat)


log4cpp
Author(s): Stephen Roderick, Bastiaan Bakker, Cedric Le Goater, Steve Ostlind, Marcel Harkema, Walter Stroebel, Glenn Scott and Tony Cheung
autogenerated on Sun Jun 23 2019 19:10:00