platform/codecs/LogCodec.hpp

00001 // ------------------------------------------------------------------------
00002 // Pion is a development platform for building Reactors that process Events
00003 // ------------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Pion is free software: you can redistribute it and/or modify it under the
00007 // terms of the GNU Affero General Public License as published by the Free
00008 // Software Foundation, either version 3 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Pion is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Affero General Public License
00017 // along with Pion.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 
00020 #ifndef __PION_LOGCODEC_HEADER__
00021 #define __PION_LOGCODEC_HEADER__
00022 
00023 #include <vector>
00024 #include <boost/bind.hpp>
00025 #include <boost/shared_ptr.hpp>
00026 #include <boost/scoped_array.hpp>
00027 #include <boost/lexical_cast.hpp>
00028 #include <pion/PionConfig.hpp>
00029 #include <pion/PionException.hpp>
00030 #include <pion/PionHashMap.hpp>
00031 #include <pion/PionDateTime.hpp>
00032 #include <pion/PionAlgorithms.hpp>
00033 #include <pion/platform/Codec.hpp>
00034 #include <pion/platform/Vocabulary.hpp>
00035 
00036 #ifdef PION_WIN32
00037 #define OSEOL "\r\n"
00038 #else
00039 #define OSEOL "\n"
00040 #endif
00041 
00042 namespace pion {        // begin namespace pion
00043 namespace plugins {     // begin namespace plugins
00044 
00045 
00049 class LogCodec :
00050     public pion::platform::Codec
00051 {
00052 public:
00053 
00055     class EmptyFieldException : public PionException {
00056     public:
00057         EmptyFieldException(const std::string& codec_id)
00058             : PionException("LogCodec configuration includes an empty field name: ", codec_id) {}
00059     };
00060 
00062     class EmptyTermException : public PionException {
00063     public:
00064         EmptyTermException(const std::string& codec_id)
00065             : PionException("LogCodec configuration is missing a term identifier: ", codec_id) {}
00066     };
00067 
00069     class UnknownTermException : public PionException {
00070     public:
00071         UnknownTermException(const std::string& term_id)
00072             : PionException("LogCodec configuration maps field to an unknown term: ", term_id) {}
00073     };
00074 
00076     class BadFormatException : public PionException {
00077     public:
00078         BadFormatException(const std::string& term_id)
00079             : PionException("LogCodec format contains an unknown term: ", term_id) {}
00080     };
00081 
00082 
00084     LogCodec(void)
00085         : pion::platform::Codec(), m_read_buf(new char[READ_BUFFER_SIZE+1]),
00086         m_read_end(m_read_buf.get() + READ_BUFFER_SIZE),
00087         m_flush_after_write(false), m_handle_elf_headers(false), m_wrote_elf_headers(false),
00088         m_time_offset(0),
00089         m_event_split(EVENT_SPLIT_SET), m_event_join(EVENT_JOIN_STRING), m_comment_chars(COMMENT_CHAR_SET),
00090         m_field_split(FIELD_SPLIT_SET), m_field_join(FIELD_JOIN_STRING), m_consume_delims(true)
00091     {}
00092 
00094     virtual ~LogCodec() {}
00095 
00097     virtual const std::string& getContentType(void) const { return CONTENT_TYPE; }
00098 
00104     virtual pion::platform::CodecPtr clone(void) const;
00105 
00112     virtual void write(std::ostream& out, const pion::platform::Event& e);
00113 
00119     virtual void finish(std::ostream& out) {};
00120 
00128     virtual bool read(std::istream& in, pion::platform::Event& e);
00129 
00137     virtual void setConfig(const pion::platform::Vocabulary& v, const xmlNodePtr config_ptr);
00138 
00145     virtual void updateVocabulary(const pion::platform::Vocabulary& v);
00146 
00148     inline void reset(void) {
00149         m_field_map.clear();
00150         m_format.clear();
00151         m_wrote_elf_headers = false;
00152     }
00153 
00154 
00155 private:
00156 
00158     struct LogField {
00160         LogField(const std::string& field, const pion::platform::Vocabulary::Term& term, char delim_start,
00161                  char delim_end, bool opt_delims, bool urlencode, char escape_char, const std::string& empty_val,
00162                  bool do_time_offset, const PionDateTime::time_duration_type& time_offset)
00163             : log_field(field), log_term(term), log_delim_start(delim_start), log_delim_end(delim_end),
00164               log_opt_delims(opt_delims), log_urlencode(urlencode), log_escape_char(escape_char),
00165               log_empty_val(empty_val), log_do_time_offset(do_time_offset), log_time_offset(time_offset)
00166         {}
00167 
00169         LogField(const LogField& f)
00170             : log_field(f.log_field), log_term(f.log_term), log_delim_start(f.log_delim_start),
00171               log_delim_end(f.log_delim_end), log_opt_delims(f.log_opt_delims),
00172               log_urlencode(f.log_urlencode), log_escape_char(f.log_escape_char),
00173               log_empty_val(f.log_empty_val), log_do_time_offset(f.log_do_time_offset), log_time_offset(f.log_time_offset)
00174         {}
00175 
00177         inline LogField& operator=(const LogField& f) {
00178             log_field = f.log_field;
00179             log_term = f.log_term;
00180             log_delim_start = f.log_delim_start;
00181             log_delim_end = f.log_delim_end;
00182             log_opt_delims = f.log_opt_delims;
00183             log_urlencode = f.log_urlencode;
00184             log_escape_char = f.log_escape_char;
00185             log_empty_val = f.log_empty_val;
00186             log_do_time_offset = f.log_do_time_offset;
00187             log_time_offset = f.log_time_offset;
00188             return *this;
00189         }
00190 
00192         inline void writeEmptyValue(std::ostream& out) const {
00193             if (log_delim_start != '\0')
00194                 out << log_delim_start;
00195             out << log_empty_val;
00196             if (log_delim_end != '\0')
00197                 out << log_delim_end;
00198         }
00199 
00206         inline void write(std::ostream& out, const pion::platform::Event::ParameterValue& value);
00207 
00214         inline void read(const char *buf, pion::platform::Event& e);
00215 
00217         std::string                         log_field;
00219         pion::platform::Vocabulary::Term    log_term;
00221         PionTimeFacet                       log_time_facet;
00223         char                                log_delim_start;
00225         char                                log_delim_end;
00227         bool                                log_opt_delims;
00229         bool                                log_urlencode;
00231         char                                log_escape_char;
00233         std::string                         log_empty_val;
00235         bool                                log_do_time_offset;
00237         PionDateTime::time_duration_type    log_time_offset;
00238     };
00239 
00241     typedef boost::shared_ptr<LogField>     LogFieldPtr;
00242 
00244     typedef PION_HASH_MAP<std::string,
00245         LogFieldPtr, PION_HASH_STRING>      FieldMap;
00246 
00248     typedef std::vector<LogFieldPtr>        CurrentFormat;
00249 
00251     typedef std::istream::traits_type       traits_type;
00252 
00254     typedef std::basic_streambuf<std::istream::char_type,
00255         std::istream::traits_type>          streambuf_type;
00256 
00258     typedef std::istream::int_type          int_type;
00259 
00260 
00273     inline void mapFieldToTerm(const std::string& field, const pion::platform::Vocabulary::Term& term,
00274                                char delim_start, char delim_end, bool opt_delims,
00275                                bool urlencode, char escape_char, const std::string& empty_val,
00276                                bool do_time_offset, const PionDateTime::time_duration_type& time_offset);
00277 
00283     inline char * cstyle(char *cstring);
00284 
00290     inline void changeELFFormat(char *fmt);
00291 
00297     inline void writeELFHeaders(std::ostream& out) const;
00298 
00307     inline int_type consumeVoidsAndComments(streambuf_type *buf_ptr);
00308 
00309 
00311     static const std::string        CONTENT_TYPE;
00312 
00314     static const std::string        FLUSH_ELEMENT_NAME;
00315 
00317     static const std::string        HEADERS_ELEMENT_NAME;
00318 
00320     static const std::string        TIME_OFFSET_ELEMENT_NAME;
00321 
00323     static const std::string        FIELD_ELEMENT_NAME;
00324 
00326     static const std::string        TERM_ATTRIBUTE_NAME;
00327 
00329     static const std::string        START_ATTRIBUTE_NAME;
00330 
00332     static const std::string        END_ATTRIBUTE_NAME;
00333 
00335     static const std::string        OPTIONAL_ATTRIBUTE_NAME;
00336 
00338     static const std::string        URLENCODE_ATTRIBUTE_NAME;
00339 
00341     static const std::string        ESCAPE_ATTRIBUTE_NAME;
00342 
00344     static const std::string        EMPTY_ATTRIBUTE_NAME;
00345 
00347     static const std::string        EVENTS_ELEMENT_NAME;
00348 
00350     static const std::string        FIELDS_ELEMENT_NAME;
00351 
00353     static const std::string        SPLIT_ATTRIBUTE_NAME;
00354 
00356     static const std::string        JOIN_ATTRIBUTE_NAME;
00357 
00359     static const std::string        COMMENT_ATTRIBUTE_NAME;
00360 
00362     static const std::string        CONSUME_ATTRIBUTE_NAME;
00363 
00365     static const unsigned int       READ_BUFFER_SIZE;
00366 
00367 
00369     static const std::string        EVENT_SPLIT_SET;
00370     static const std::string        EVENT_JOIN_STRING;
00371     static const std::string        COMMENT_CHAR_SET;
00372     static const std::string        FIELD_SPLIT_SET;
00373     static const std::string        FIELD_JOIN_STRING;
00374     static const bool               CONSUME_DELIMS_FLAG;
00375 
00376 
00378     static const std::string        VERSION_ELF_HEADER;
00379     static const std::string        DATE_ELF_HEADER;
00380     static const std::string        SOFTWARE_ELF_HEADER;
00381     static const std::string        FIELDS_ELF_HEADER;
00382 
00383 
00385     boost::scoped_array<char>       m_read_buf;
00386 
00388     const char * const              m_read_end;
00389 
00391     FieldMap                        m_field_map;
00392 
00394     CurrentFormat                   m_format;
00395 
00397     bool                            m_flush_after_write;
00398 
00400     bool                            m_handle_elf_headers;
00401 
00403     bool                            m_wrote_elf_headers;
00404 
00406     boost::int32_t                  m_time_offset;
00407 
00409     std::string                     m_event_split;
00410 
00412     std::string                     m_event_join;
00413 
00415     std::string                     m_comment_chars;
00416 
00418     std::string                     m_field_split;
00419 
00421     std::string                     m_field_join;
00422 
00424     bool                            m_consume_delims;
00425 };
00426 
00427 
00428 // inline member functions for LogCodec
00429 
00430 inline void LogCodec::mapFieldToTerm(const std::string& field, const pion::platform::Vocabulary::Term& term,
00431                                      char delim_start, char delim_end, bool opt_delims,
00432                                      bool urlencode, char escape_char, const std::string& empty_val,
00433                                      bool do_time_offset, const PionDateTime::time_duration_type& time_offset)
00434 {
00435     for (FieldMap::const_iterator i = m_field_map.begin(); i != m_field_map.end(); ++i) {
00436         if (i->second->log_term.term_ref == term.term_ref)
00437             throw PionException("Duplicate Field Term");
00438     }
00439 
00440     if (m_field_map.find(field) != m_field_map.end())
00441         throw PionException("Duplicate Field Name");
00442 
00443     // prepare a new Logfield object
00444     LogFieldPtr field_ptr(new LogField(field, term, delim_start, delim_end, opt_delims, urlencode, escape_char, empty_val, do_time_offset, time_offset));
00445     switch (term.term_type) {
00446         case pion::platform::Vocabulary::TYPE_DATE_TIME:
00447         case pion::platform::Vocabulary::TYPE_DATE:
00448         case pion::platform::Vocabulary::TYPE_TIME:
00449             field_ptr->log_time_facet.setFormat(term.term_format);
00450             break;
00451         default:
00452             break; // do nothing
00453     }
00454     // add it to the mapping of field names
00455     m_field_map[field] = field_ptr;
00456     // append the new field to the current (default) format
00457     m_format.push_back(field_ptr);
00458 }
00459 
00460 inline char * LogCodec::cstyle(char *cstring)
00461 {
00462     char *ptr = cstring;
00463     size_t len = strlen(cstring);
00464     size_t num, nlen;
00465 
00466     while ( (ptr = strchr(ptr, '\\')) ) {
00467         nlen = 1;
00468         switch (ptr[1]) {
00469         case 'a': *ptr = '\a'; break;
00470         case 'b': *ptr = '\b'; break;
00471         case 'f': *ptr = '\f'; break;
00472         case 'n': *ptr = '\n'; break;
00473         case 'r': *ptr = '\r'; break;
00474         case 't': *ptr = '\t'; break;
00475         case 'v': *ptr = '\v'; break;
00476         case '_': *ptr = ' '; break;
00477         case '0': case '1': case '2': case '3':
00478         case '4': case '5': case '6': case '7':
00479             nlen = sscanf(ptr + 1, "%o", &num);
00480             *ptr = (char)num;
00481             break;
00482         case 'x':
00483             nlen = sscanf(ptr + 1, "%x", &num);
00484             *ptr = (char)num;
00485             break;
00486         }
00487         num = ptr - cstring + nlen;
00488         ptr++;
00489         memmove(ptr, ptr + nlen, len - num);
00490     }
00491 
00492     return cstring;
00493 }
00494 
00495 inline void LogCodec::changeELFFormat(char *fmt)
00496 {
00497     m_format.clear();
00498     char *ptr;
00499     bool last_field = false;
00500     while (!last_field && *fmt != '\0' && m_event_split.find(*fmt) == std::string::npos) {
00501         // skip leading spaces
00502         while (*fmt == ' ') ++fmt;
00503         // find the end of the field name
00504         ptr = fmt;
00505         while (*ptr != '\0' && m_event_split.find(*ptr) == std::string::npos && *ptr != ' ') ++ptr;
00506         // set last_field if we're at the end
00507         if (*ptr == '\0' || m_event_split.find(*ptr) != std::string::npos) last_field = true;
00508         *ptr = '\0';
00509         FieldMap::const_iterator i = m_field_map.find(fmt);
00510         if (i == m_field_map.end())
00511             throw BadFormatException(fmt);
00512         m_format.push_back(i->second);
00513         fmt = ptr + 1;
00514     }
00515 }
00516 
00517 inline void LogCodec::writeELFHeaders(std::ostream& out) const
00518 {
00519     PionDateTime time_now(boost::posix_time::second_clock::universal_time());
00520     out << VERSION_ELF_HEADER << " 1.0" << m_event_join;
00521     out << DATE_ELF_HEADER << ' ' << time_now << m_event_join;
00522     out << SOFTWARE_ELF_HEADER << " Pion v" << PION_VERSION << m_event_join;
00523     out << FIELDS_ELF_HEADER;
00524     CurrentFormat::const_iterator i = m_format.begin();
00525     while (i != m_format.end())
00526         out << ' ' << (*i++)->log_field;
00527     out << m_event_join;
00528 }
00529 
00530 inline LogCodec::int_type LogCodec::consumeVoidsAndComments(streambuf_type *buf_ptr)
00531 {
00532     int_type c = buf_ptr->sgetc();
00533     char * const read_buf = m_read_buf.get();
00534     char * read_ptr;
00535 
00536     while (!traits_type::eq_int_type(c, traits_type::eof())) {
00537         if (m_field_split.find(c) != std::string::npos || m_event_split.find(c) != std::string::npos) {
00538             c = buf_ptr->snextc();
00539         } else if (m_comment_chars.find(c) != std::string::npos) {
00540             // ignore comment line (sorta...)
00541             read_ptr = read_buf;
00542             do {
00543                 // check for end of line
00544                 if (m_event_split.find(c) != std::string::npos)
00545                     break;
00546                 // read in the comment in case it matters...
00547                 if (read_ptr < m_read_end)
00548                     *(read_ptr++) = c;
00549                 // get the next character
00550                 c = buf_ptr->snextc();
00551             } while (!traits_type::eq_int_type(c, traits_type::eof()));
00552             *read_ptr = '\0';
00553             if (m_handle_elf_headers) {
00554                 // check if it is an ELF format change
00555                 read_buf[FIELDS_ELF_HEADER.size()] = '\0';
00556                 if (FIELDS_ELF_HEADER == read_buf)
00557                     changeELFFormat(read_buf + FIELDS_ELF_HEADER.size() + 1);
00558             }
00559         } else {
00560             break;
00561         }
00562     }
00563     return c;
00564 }
00565 
00566 
00567 // inline member functions for LogCodec::LogField
00568 
00569 inline void LogCodec::LogField::write(std::ostream& out, const pion::platform::Event::ParameterValue& value)
00570 {
00571     std::ostringstream oss;
00572 
00573     switch(log_term.term_type) {
00574         case pion::platform::Vocabulary::TYPE_NULL:
00575         case pion::platform::Vocabulary::TYPE_OBJECT:
00576             break;  // ignore unsupported field
00577         case pion::platform::Vocabulary::TYPE_INT8:
00578         case pion::platform::Vocabulary::TYPE_INT16:
00579         case pion::platform::Vocabulary::TYPE_INT32:
00580             oss << boost::get<boost::int32_t>(value);
00581             break;
00582         case pion::platform::Vocabulary::TYPE_INT64:
00583             oss << boost::get<boost::int64_t>(value);
00584             break;
00585         case pion::platform::Vocabulary::TYPE_UINT8:
00586         case pion::platform::Vocabulary::TYPE_UINT16:
00587         case pion::platform::Vocabulary::TYPE_UINT32:
00588             oss << boost::get<boost::uint32_t>(value);
00589             break;
00590         case pion::platform::Vocabulary::TYPE_UINT64:
00591             oss << boost::get<boost::uint64_t>(value);
00592             break;
00593         case pion::platform::Vocabulary::TYPE_FLOAT:
00594             oss << boost::get<float>(value);
00595             break;
00596         case pion::platform::Vocabulary::TYPE_DOUBLE:
00597             // using boost::lexical_cast<std::string> ensures precision appropriate to type double
00598             oss << boost::lexical_cast<std::string>(boost::get<double>(value));
00599             break;
00600         case pion::platform::Vocabulary::TYPE_LONG_DOUBLE:
00601             // using boost::lexical_cast<std::string> ensures precision appropriate to type long double
00602             oss << boost::lexical_cast<std::string>(boost::get<long double>(value));
00603             break;
00604         case pion::platform::Vocabulary::TYPE_SHORT_STRING:
00605         case pion::platform::Vocabulary::TYPE_STRING:
00606         case pion::platform::Vocabulary::TYPE_LONG_STRING:
00607         case pion::platform::Vocabulary::TYPE_BLOB:
00608         case pion::platform::Vocabulary::TYPE_ZBLOB:
00609         {
00610             const pion::platform::Event::BlobType& ss = boost::get<const pion::platform::Event::BlobType&>(value);
00611             if (ss.size() > 0) {
00612                 if (log_urlencode) {
00613                     std::string temp_str(ss.get());
00614                     oss << algo::url_encode(temp_str);
00615                 } else {
00616                     oss.write(ss.get(), ss.size());
00617                 }
00618             }
00619             break;
00620         }
00621         case pion::platform::Vocabulary::TYPE_CHAR:
00622         {
00623             const pion::platform::Event::BlobType& ss = boost::get<const pion::platform::Event::BlobType&>(value);
00624             if (ss.size() > 0) {
00625                 if (log_urlencode) {
00626                     std::string temp_str(ss.get());
00627                     temp_str = algo::url_encode(temp_str);
00628                     if (temp_str.size() > log_term.term_size)
00629                         temp_str.resize(log_term.term_size);
00630                     oss << temp_str;
00631                 } else {
00632                     oss.write(ss.get(), ss.size() < log_term.term_size ? ss.size() : log_term.term_size);
00633                 }
00634             }
00635             break;
00636         }
00637         case pion::platform::Vocabulary::TYPE_DATE_TIME:
00638         case pion::platform::Vocabulary::TYPE_DATE:
00639         case pion::platform::Vocabulary::TYPE_TIME:
00640         {
00641             PionDateTime dt = boost::get<const PionDateTime&>(value);
00642             if (log_do_time_offset) {
00643                 dt -= log_time_offset;
00644             }
00645             if (log_urlencode) {
00646                 std::string temp_str;
00647                 log_time_facet.toString(temp_str, dt);
00648                 oss << algo::url_encode(temp_str);
00649             } else {
00650                 log_time_facet.write(oss, dt);
00651             }
00652             break;
00653         }
00654     }
00655 
00656     if (log_delim_start != '\0')
00657         out << log_delim_start;
00658     if (oss.str().empty())
00659         out << log_empty_val;
00660     else {
00661         std::string src = oss.str();
00662         std::string dst;
00663         for (std::string::iterator i = src.begin(); i != src.end(); i++) {
00664             if (*i == log_delim_end)
00665                 dst.push_back(log_escape_char);
00666             dst.push_back(*i);
00667         }
00668         out << dst;
00669     }
00670     if (log_delim_end != '\0')
00671         out << log_delim_end;
00672 }
00673 
00674 inline void LogCodec::LogField::read(const char *buf, pion::platform::Event& e)
00675 {
00676     switch(log_term.term_type) {
00677         case pion::platform::Vocabulary::TYPE_NULL:
00678         case pion::platform::Vocabulary::TYPE_OBJECT:
00679             break;  // ignore unsupported field
00680         case pion::platform::Vocabulary::TYPE_INT8:
00681         case pion::platform::Vocabulary::TYPE_INT16:
00682         case pion::platform::Vocabulary::TYPE_INT32:
00683             e.setInt(log_term.term_ref, boost::lexical_cast<boost::int32_t>(buf));
00684             break;
00685         case pion::platform::Vocabulary::TYPE_INT64:
00686             e.setBigInt(log_term.term_ref, boost::lexical_cast<boost::int64_t>(buf));
00687             break;
00688         case pion::platform::Vocabulary::TYPE_UINT8:
00689         case pion::platform::Vocabulary::TYPE_UINT16:
00690         case pion::platform::Vocabulary::TYPE_UINT32:
00691             e.setUInt(log_term.term_ref, boost::lexical_cast<boost::uint32_t>(buf));
00692             break;
00693         case pion::platform::Vocabulary::TYPE_UINT64:
00694             e.setUBigInt(log_term.term_ref, boost::lexical_cast<boost::uint64_t>(buf));
00695             break;
00696         case pion::platform::Vocabulary::TYPE_FLOAT:
00697             e.setFloat(log_term.term_ref, boost::lexical_cast<float>(buf));
00698             break;
00699         case pion::platform::Vocabulary::TYPE_DOUBLE:
00700             e.setDouble(log_term.term_ref, boost::lexical_cast<double>(buf));
00701             break;
00702         case pion::platform::Vocabulary::TYPE_LONG_DOUBLE:
00703             e.setLongDouble(log_term.term_ref, boost::lexical_cast<long double>(buf));
00704             break;
00705         case pion::platform::Vocabulary::TYPE_SHORT_STRING:
00706         case pion::platform::Vocabulary::TYPE_STRING:
00707         case pion::platform::Vocabulary::TYPE_LONG_STRING:
00708         case pion::platform::Vocabulary::TYPE_BLOB:
00709         case pion::platform::Vocabulary::TYPE_ZBLOB:
00710             if (log_urlencode) {
00711                 std::string temp_str(algo::url_decode(buf));
00712                 e.setString(log_term.term_ref, temp_str);
00713             } else {
00714                 e.setString(log_term.term_ref, buf);
00715             }
00716             break;
00717         case pion::platform::Vocabulary::TYPE_CHAR:
00718             if (log_urlencode) {
00719                 std::string temp_str(algo::url_decode(buf));
00720                 if (temp_str.size() > log_term.term_size)
00721                     temp_str.resize(log_term.term_size);
00722                 e.setString(log_term.term_ref, temp_str);
00723             } else if (strlen(buf) > log_term.term_size) {
00724                 e.setString(log_term.term_ref, std::string(buf, log_term.term_size));
00725             } else {
00726                 e.setString(log_term.term_ref, buf);
00727             }
00728             break;
00729         case pion::platform::Vocabulary::TYPE_DATE_TIME:
00730         case pion::platform::Vocabulary::TYPE_DATE:
00731         case pion::platform::Vocabulary::TYPE_TIME:
00732         {
00733             PionDateTime dt;
00734             if (log_urlencode) {
00735                 std::string temp_str(algo::url_decode(buf));
00736                 log_time_facet.fromString(temp_str, dt);
00737             } else {
00738                 log_time_facet.fromString(buf, dt);
00739             }
00740             if (log_do_time_offset) {
00741                 dt += log_time_offset;
00742             }
00743             e.setDateTime(log_term.term_ref, dt);
00744             break;
00745         }
00746     }
00747 }
00748 
00749 
00750 }   // end namespace plugins
00751 }   // end namespace pion
00752 
00753 #endif

Generated on Wed Apr 13 16:38:33 2011 for pion-platform by  doxygen 1.4.7