22#include <com/sun/star/logging/XCsvLogFormatter.hpp>
23#include <com/sun/star/uno/XComponentContext.hpp>
24#include <com/sun/star/lang/XServiceInfo.hpp>
25#include <com/sun/star/lang/IllegalArgumentException.hpp>
30#include <rtl/ustrbuf.hxx>
39 using ::com::sun::star::uno::Sequence;
40 using ::com::sun::star::logging::LogRecord;
45 class CsvFormatter :
public cppu::WeakImplHelper<css::logging::XCsvLogFormatter, css::lang::XServiceInfo>
48 virtual OUString SAL_CALL formatMultiColumn(
const Sequence< OUString>& column_data)
override;
54 virtual sal_Bool SAL_CALL getLogEventNo()
override;
55 virtual sal_Bool SAL_CALL getLogThread()
override;
56 virtual sal_Bool SAL_CALL getLogTimestamp()
override;
57 virtual sal_Bool SAL_CALL getLogSource()
override;
58 virtual Sequence< OUString > SAL_CALL getColumnnames()
override;
60 virtual void SAL_CALL setLogEventNo(
sal_Bool log_event_no )
override;
61 virtual void SAL_CALL setLogThread(
sal_Bool log_thread )
override;
62 virtual void SAL_CALL setLogTimestamp(
sal_Bool log_timestamp )
override;
63 virtual void SAL_CALL setLogSource(
sal_Bool log_source )
override;
64 virtual void SAL_CALL setColumnnames(
const Sequence< OUString>& column_names)
override;
67 virtual OUString SAL_CALL getHead( )
override;
68 virtual OUString SAL_CALL format(
const LogRecord& Record )
override;
69 virtual OUString SAL_CALL getTail( )
override;
93 constexpr OUStringLiteral dos_newline =
u"\r\n";
95 bool needsQuoting(std::u16string_view str)
97 return str.find_first_of(
u"\",\n\r") != std::u16string_view::npos;
100 void appendEncodedString(OUStringBuffer& buf, std::u16string_view str)
102 if(needsQuoting(str))
105 buf.append(quote_char);
106 const sal_Int32 buf_offset = buf.getLength();
107 const size_t str_length = str.size();
110 if(quote_char==str[str_length-1])
111 buf.append(quote_char);
114 for(
size_t i = str_length;; )
117 i=str.substr(i).rfind(quote_char);
118 if(i==std::u16string_view::npos)
120 buf.insert(buf_offset + i, quote_char);
122 buf.append(quote_char);
131 CsvFormatter::CsvFormatter()
140 sal_Bool CsvFormatter::getLogEventNo()
145 sal_Bool CsvFormatter::getLogThread()
150 sal_Bool CsvFormatter::getLogTimestamp()
155 sal_Bool CsvFormatter::getLogSource()
160 Sequence< OUString > CsvFormatter::getColumnnames()
165 void CsvFormatter::setLogEventNo(
sal_Bool log_event_no)
170 void CsvFormatter::setLogThread(
sal_Bool log_thread)
175 void CsvFormatter::setLogTimestamp(
sal_Bool log_timestamp)
180 void CsvFormatter::setLogSource(
sal_Bool log_source)
185 void CsvFormatter::setColumnnames(
const Sequence< OUString >& columnnames)
191 OUString SAL_CALL CsvFormatter::getHead( )
195 buf.append(
"event no,");
197 buf.append(
"thread,");
199 buf.append(
"timestamp,");
201 buf.append(
"class,method,");
203 for(sal_Int32 i=0;
i<columns;
i++)
207 buf.setLength(buf.getLength()-1);
208 buf.append(dos_newline);
209 return buf.makeStringAndClear();
212 OUString SAL_CALL CsvFormatter::format(
const LogRecord& record )
214 OUStringBuffer aLogEntry;
218 aLogEntry.append(record.SequenceNumber + comma_char);
223 aLogEntry.append(record.ThreadID + OUStringChar(comma_char));
228 if ( record.LogTime.Year < -9999 || 9999 < record.LogTime.Year
229 || record.LogTime.Month < 1 || 12 < record.LogTime.Month
230 || record.LogTime.Day < 1 || 31 < record.LogTime.Day
231 || 24 < record.LogTime.Hours
232 || 60 < record.LogTime.Minutes
233 || 60 < record.LogTime.Seconds
234 || 999999999 < record.LogTime.NanoSeconds)
236 throw css::lang::IllegalArgumentException(
"invalid date",
static_cast<cppu::OWeakObject*
>(
this), 1);
240 char buffer[
SAL_N_ELEMENTS(
"-32768-65535-65535T65535:65535:65535.4294967295") ];
241 const size_t buffer_size =
sizeof( buffer );
242 snprintf( buffer, buffer_size,
"%04i-%02u-%02uT%02u:%02u:%02u.%09" SAL_PRIuUINT32,
243 static_cast<int>(record.LogTime.Year),
244 static_cast<unsigned int>(record.LogTime.Month),
245 static_cast<unsigned int>(record.LogTime.Day),
246 static_cast<unsigned int>(record.LogTime.Hours),
247 static_cast<unsigned int>(record.LogTime.Minutes),
248 static_cast<unsigned int>(record.LogTime.Seconds),
249 record.LogTime.NanoSeconds );
250 aLogEntry.appendAscii( buffer );
251 aLogEntry.append(comma_char);
256 appendEncodedString(aLogEntry, record.SourceClassName);
257 aLogEntry.append(comma_char);
259 appendEncodedString(aLogEntry, record.SourceMethodName);
260 aLogEntry.append(comma_char);
268 aLogEntry.append(record.Message);
270 appendEncodedString(aLogEntry, record.Message);
272 aLogEntry.append( dos_newline );
273 return aLogEntry.makeStringAndClear();
276 OUString SAL_CALL CsvFormatter::getTail( )
281 OUString SAL_CALL CsvFormatter::formatMultiColumn(
const Sequence< OUString>& column_data)
283 sal_Int32 columns = column_data.getLength();
285 for(
int i=0;
i<columns;
i++)
287 appendEncodedString(buf, column_data[i]);
288 buf.append(comma_char);
290 buf.setLength(buf.getLength()-1);
291 return buf.makeStringAndClear();
294 sal_Bool SAL_CALL CsvFormatter::supportsService(
const OUString& service_name )
299 OUString SAL_CALL CsvFormatter::getImplementationName()
301 return "com.sun.star.comp.extensions.CsvFormatter";
304 Sequence< OUString > SAL_CALL CsvFormatter::getSupportedServiceNames()
306 return {
"com.sun.star.logging.CsvFormatter" };
311extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
313 css::uno::XComponentContext *,
314 css::uno::Sequence<css::uno::Any>
const &)
316 return cppu::acquire(
new logging::CsvFormatter());
#define SAL_N_ELEMENTS(arr)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)