Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 # include "Errata.h"
00024 # include <iostream>
00025 # include <sstream>
00026 # include <iomanip>
00027 # include <algorithm>
00028 # include <memory.h>
00029 
00030 namespace ts {
00031 
00032 
00033 
00034 namespace {
00035   std::deque<Errata::Sink::Handle> Sink_List;
00036 }
00037 
00038 std::string const Errata::DEFAULT_GLUE("\n");
00039 Errata::Message const Errata::NIL_MESSAGE;
00040 Errata::Code Errata::Message::Default_Code = 0;
00041 Errata::Message::SuccessTest const Errata::Message::DEFAULT_SUCCESS_TEST =
00042   &Errata::Message::isCodeZero;
00043 Errata::Message::SuccessTest Errata::Message::Success_Test =
00044   Errata::Message::DEFAULT_SUCCESS_TEST;
00045 
00046 bool
00047 Errata::Message::isCodeZero(Message const& msg) {
00048   return msg.m_code == 0;
00049 }
00050 
00051 void
00052 Errata::Data::push(Message const& msg) {
00053   m_items.push_back(msg);
00054 }
00055 
00056 Errata::Message const&
00057 Errata::Data::top() const {
00058   return m_items.size() ? m_items.back() : NIL_MESSAGE ;
00059 }
00060 
00061 inline Errata::Errata(ImpPtr const& ptr) 
00062   : m_data(ptr) {
00063 }
00064 
00065 Errata::Data::~Data() {
00066   if (m_log_on_delete) {
00067     Errata tmp(this); 
00068     std::deque<Errata::Sink::Handle>::iterator spot, limit;
00069     for ( spot = Sink_List.begin(), limit = Sink_List.end();
00070           spot != limit;
00071           ++spot
00072     ) {
00073       (**spot)(tmp);
00074     }
00075     tmp.m_data.release(); 
00076   }
00077 }
00078 
00079 Errata::Errata() {
00080 }
00081 
00082 Errata::Errata(self const& that)
00083   : m_data(that.m_data) {
00084 }
00085 
00086 Errata::Errata(std::string const& text) {
00087   this->push(text);
00088 }
00089 
00090 Errata::Errata(Id id, std::string const& text) {
00091   this->push(id, text);
00092 }
00093 
00094 Errata::~Errata() {
00095 }
00096 
00097 
00098 
00099 
00100 
00101 Errata::Data*
00102 Errata::pre_write() {
00103   if (m_data) {
00104     if (m_data.useCount() > 1) {
00105       m_data = new Data(*m_data); 
00106     }
00107   } else { 
00108     m_data = new Data;
00109   }
00110   return m_data.get();
00111 }
00112 
00113 
00114 Errata::Data*
00115 Errata::instance() {
00116   if (!m_data) m_data = new Data;
00117   return m_data.get();
00118 }
00119 
00120 Errata&
00121 Errata::push(Message const& msg) {
00122   this->pre_write()->push(msg);
00123   return *this;
00124 }
00125 
00126 Errata&
00127 Errata::operator=(self const& that) {
00128   m_data = that.m_data;
00129   return *this;
00130 }
00131 
00132 Errata&
00133 Errata::operator = (Message const& msg) {
00134   
00135   if (!m_data || m_data.useCount() > 1) {
00136     this->clear();
00137     this->push(msg);
00138   } else {
00139     m_data->m_items.clear();
00140     m_data->push(msg);
00141   }
00142   return *this;
00143 }
00144 
00145 Errata&
00146 Errata::pull(self& that) {
00147   if (that.m_data) {
00148     this->pre_write();
00149     m_data->m_items.insert(
00150       m_data->m_items.end(),
00151       that.m_data->m_items.begin(),
00152       that.m_data->m_items.end()
00153     );
00154     that.m_data->m_items.clear();
00155   }
00156   return *this;
00157 }
00158 
00159 void
00160 Errata::pop() {
00161   if (m_data && m_data->size()) {
00162     this->pre_write()->m_items.pop_front();
00163   }
00164   return;
00165 }
00166 
00167 void
00168 Errata::clear() {
00169   m_data.reset(0);
00170 }
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 static Errata::Container NIL_CONTAINER;
00183 
00184 Errata::iterator
00185 Errata::begin() {
00186   return m_data ? m_data->m_items.rbegin() : NIL_CONTAINER.rbegin();
00187 }
00188 
00189 Errata::const_iterator
00190 Errata::begin() const {
00191   return m_data ? static_cast<Data const&>(*m_data).m_items.rbegin()
00192     : static_cast<Container const&>(NIL_CONTAINER).rbegin();
00193 }
00194 
00195 Errata::iterator
00196 Errata::end() {
00197   return m_data ? m_data->m_items.rend() : NIL_CONTAINER.rend();
00198 }
00199 
00200 Errata::const_iterator
00201 Errata::end() const {
00202   return m_data ? static_cast<Data const&>(*m_data).m_items.rend()
00203     : static_cast<Container const&>(NIL_CONTAINER).rend();
00204 }
00205 
00206 void
00207 Errata::registerSink(Sink::Handle const& s) {
00208   Sink_List.push_back(s);
00209 }
00210 
00211 std::ostream&
00212 Errata::write(
00213   std::ostream& out,
00214   int offset,
00215   int indent,
00216   int shift,
00217   char const* lead
00218 ) const {
00219   for ( const_iterator spot = this->begin(), limit = this->end();
00220         spot != limit;
00221         ++spot
00222   ) {
00223     if ((offset + indent) > 0)
00224       out << std::setw(indent + offset) << std::setfill(' ')
00225           << ((indent > 0 && lead) ? lead : " ");
00226 
00227     out << spot->m_id << " [" << spot->m_code << "]: " << spot->m_text
00228         << std::endl
00229       ;
00230     if (spot->getErrata().size())
00231       spot->getErrata().write(out, offset, indent+shift, shift, lead);
00232 
00233   }
00234   return out;
00235 }
00236 
00237 size_t
00238 Errata::write(
00239   char *buff,
00240   size_t n,
00241   int offset,
00242   int indent,
00243   int shift,
00244   char const* lead
00245 ) const {
00246   std::ostringstream out;
00247   std::string text;
00248   this->write(out, offset, indent, shift, lead);
00249   text = out.str();
00250   memcpy(buff, text.data(), std::min(n, text.size()));
00251   return text.size();
00252 }
00253 
00254 std::ostream& operator<< (std::ostream& os, Errata const& err) {
00255   return err.write(os, 0, 0, 2, "> ");
00256 }
00257 
00258 # if USING_BOOST
00259 
00260 std::ostream&
00261 errata::format(std::ostream& s, std::string const& fmt, std::string const& glue) const {
00262   return this->format(s, boost::format(fmt), glue);
00263 }
00264 
00265 std::ostream&
00266 errata::format(std::ostream& s, boost::format const& fmt, std::string const& glue) const {
00267   if (_data) {
00268     bool inside = false;
00269     boost::format f(fmt);
00270     f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
00271     const_iterator spot(this->begin()), limit(this->end());
00272     while (spot != limit) {
00273       if (inside) s << glue;
00274       s << ( f % spot->_id % spot->_text );
00275       inside = true;
00276       ++spot;
00277     }
00278   }
00279   return s;
00280 }
00281 
00282 std::string
00283 errata::format(std::string const& fmt, std::string const& glue) const {
00284   return this->format(boost::format(fmt), glue);
00285 }
00286 
00287 std::string
00288 errata::format(boost::format const& fmt, std::string const& glue) const {
00289   std::ostringstream s;
00290   this->format(s, fmt, glue);
00291   return s.str();
00292 }
00293 
00294 # endif
00295 
00296 } 
00297