• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

Errata.h

Go to the documentation of this file.
00001 # if !defined TS_ERRATA_HEADER
00002 # define TS_ERRATA_HEADER
00003 
00004 /** @file
00005     Stacking error message handling.
00006 
00007     The problem addressed by this library is the ability to pass back
00008     detailed error messages from failures. It is hard to get good
00009     diagnostics because the specific failures and general context are
00010     located in very different stack frames. This library allows local
00011     functions to pass back local messages which can be easily
00012     augmented as the error travels up the stack frame.
00013 
00014     This could be done with exceptions but
00015     - That is more effort to implemention
00016     - Generally more expensive.
00017 
00018     Each message on a stack contains text and a numeric identifier.
00019     The identifier value zero is reserved for messages that are not
00020     errors so that information can be passed back even in the success
00021     case.
00022 
00023     The implementation takes the position that success is fast and
00024     failure is expensive. Therefore it is optimized for the success
00025     path, imposing very little overhead. On the other hand, if an
00026     error occurs and is handled, that is generally so expensive that
00027     optimizations are pointless (although, of course, one should not
00028     be gratuitiously expensive).
00029 
00030     The library also provides the @c Rv ("return value") template to
00031     make returning values and status easier. This template allows a
00032     function to return a value and status pair with minimal changes.
00033     The pair acts like the value type in most situations, while
00034     providing access to the status.
00035 
00036     Each instance of an erratum is a wrapper class that emulates value
00037     semantics (copy on write). This means passing even large message
00038     stacks is inexpensive, involving only a pointer copy and reference
00039     counter increment and decrement. A success value is represented by
00040     an internal @c NULL so it is even cheaper to copy.
00041 
00042     To further ease use, the library has the ability to define @a
00043     sinks.  A sink is a function that acts on an erratum when it
00044     becomes unreferenced. The indended use is to send the messages to
00045     an output log. This makes reporting errors to a log from even
00046     deeply nested functions easy while preserving the ability of the
00047     top level logic to control such logging.
00048 
00049     @section license License
00050 
00051     Licensed to the Apache Software Foundation (ASF) under one
00052     or more contributor license agreements.  See the NOTICE file
00053     distributed with this work for additional information
00054     regarding copyright ownership.  The ASF licenses this file
00055     to you under the Apache License, Version 2.0 (the
00056     "License"); you may not use this file except in compliance
00057     with the License.  You may obtain a copy of the License at
00058 
00059     http://www.apache.org/licenses/LICENSE-2.0
00060 
00061     Unless required by applicable law or agreed to in writing, software
00062     distributed under the License is distributed on an "AS IS" BASIS,
00063     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00064     See the License for the specific language governing permissions and
00065     limitations under the License.
00066  */
00067 
00068 # include <memory>
00069 # include <string>
00070 # include <iosfwd>
00071 # include <deque>
00072 # include "NumericType.h"
00073 # include "IntrusivePtr.h"
00074 
00075 # if USING_BOOST
00076 #   include <boost/function.hpp>
00077 #   include <boost/format/format_fwd.hpp>
00078 # endif
00079 
00080 namespace ts {
00081 
00082 /** Class to hold a stack of error messages (the "errata").
00083     This is a smart handle class, which wraps the actual data
00084     and can therefore be treated a value type with cheap copy
00085     semantics. Default construction is very cheap.
00086  */
00087 class Errata {
00088 protected:
00089     /// Implementation class.
00090     struct Data;
00091     /// Handle for implementation class instance.
00092     typedef IntrusivePtr<Data> ImpPtr;
00093 public:
00094     typedef Errata self; /// Self reference type.
00095 
00096     /// Message ID.
00097     typedef NumericType<unsigned int, struct MsgIdTag> Id;
00098 
00099     /* Tag / level / code severity.
00100        This is intended for clients to use to provide additional
00101        classification of a message. A severity code, as for syslog,
00102        is a common use.
00103 
00104     */
00105     typedef NumericType<unsigned int, struct CodeTag> Code;
00106     struct Message;
00107 
00108     typedef std::deque<Message> Container; ///< Storage type for messages.
00109     // We iterate backwards to look like a stack.
00110 //    typedef Container::reverse_iterator iterator; ///< Message iteration.
00111     /// Message const iteration.
00112 //    typedef Container::const_reverse_iterator const_iterator;
00113     /// Reverse message iteration.
00114 //    typedef Container::iterator reverse_iterator;
00115     /// Reverse constant message iteration.
00116 //    typedef Container::const_iterator const_reverse_iterator;
00117     
00118     /// Default constructor - empty errata, very fast.
00119     Errata();
00120     /// Copy constructor, very fast.
00121     Errata (
00122         self const& that ///< Object to copy
00123     );
00124     /// Construct from string.
00125     /// Message Id and Code are default.
00126     explicit Errata(
00127         std::string const& text ///< Finalized message text.
00128     );
00129     /// Construct with @a id and @a text.
00130     /// Code is default.
00131     Errata(
00132       Id id, ///< Message id.
00133       std::string const& text ///< Message text.
00134     );
00135     /// Construct with @a id, @a code, and @a text.
00136     Errata(
00137       Id id, ///< Message text.
00138       Code code, ///< Message code.
00139       std::string const& text ///< Message text.
00140     );
00141     /** Construct from a message instance.
00142         This is equivalent to default constructing an @c errata and then
00143         invoking @c push with an argument of @a msg.
00144     */
00145     Errata(
00146       Message const& msg ///< Message to push
00147     );
00148 
00149     /// destructor
00150     ~Errata();
00151 
00152     /// Self assignment.
00153     /// @return A reference to this object.
00154     self& operator = (
00155       const self& that ///< Source instance.
00156     );
00157 
00158     /** Assign message.
00159         All other messages are discarded.
00160         @return A reference to this object.
00161     */
00162     self& operator = (
00163       Message const& msg ///< Source message.
00164     );
00165 
00166     /** Push @a text as a message.
00167         The message is constructed from just the @a text.
00168         It becomes the top message.
00169         @return A reference to this object.
00170     */
00171     self& push(std::string const& text);
00172     /** Push @a text as a message with message @a id.
00173         The message is constructed from @a text and @a id.
00174         It becomes the top message.
00175         @return A reference to this object.
00176     */
00177     self& push(Id id, std::string const& text);
00178     /** Push @a text as a message with message @a id and @a code.
00179         The message is constructed from @a text and @a id.
00180         It becomes the top message.
00181         @return A reference to this object.
00182     */
00183     self& push(Id id, Code code, std::string const& text);
00184     /** Push a message.
00185         @a msg becomes the top message.
00186         @return A reference to this object.
00187     */
00188     self& push(Message const& msg);
00189 
00190     /** Push a nested status.
00191         @a err becomes the top item.
00192         @return A reference to this object.
00193     */
00194     self& push(self const& err);
00195 
00196     /** Access top message.
00197         @return If the errata is empty, a default constructed message
00198         otherwise the most recent message.
00199      */
00200     Message const& top() const;
00201 
00202     /** Move messages from @a that to @c this errata.
00203         Messages from @a that are put on the top of the
00204         stack in @c this and removed from @a that.
00205     */
00206     self& pull(self& that);
00207 
00208     /// Remove last message.
00209     void pop();
00210 
00211     /// Remove all messages.
00212     void clear();
00213 
00214     /** Inhibit logging.
00215         @note This only affects @c this as a top level @c errata.
00216         It has no effect on this @c this being logged as a nested
00217         @c errata.
00218     */
00219     self& doNotLog();
00220 
00221     friend std::ostream& operator<< (std::ostream&, self const&);
00222 
00223     /// Default glue value (a newline) for text rendering.
00224     static std::string const DEFAULT_GLUE;
00225 
00226     /** Test status.
00227 
00228         Equivalent to @c success but more convenient for use in
00229         control statements.
00230 
00231         @return @c true if no messages or last message has a zero
00232         message ID, @c false otherwise.
00233      */
00234     operator bool() const;
00235 
00236     /** Test errata for no failure condition.
00237 
00238         Equivalent to @c operator @c bool but easier to invoke.
00239 
00240         @return @c true if no messages or last message has a zero
00241         message ID, @c false otherwise.
00242      */
00243     bool isOK() const;
00244 
00245     /// Number of messages in the errata.
00246     size_t size() const;
00247 
00248     /*  Forward declares.
00249         We have to make our own iterators as the least bad option. The problem
00250         is that we have recursive structures so declaration order is difficult.
00251         We can't use the container iterators here because the element type is
00252         not yet defined. If we define the element type here, it can't contain
00253         an Errata and we have to do funky things to get around that. So we
00254         have our own iterators, which are just shadowing sublclasses of the
00255         container iterators.
00256      */
00257     class iterator;
00258     class const_iterator;
00259 
00260     /// Reference to top item on the stack.
00261     iterator begin();
00262     /// Reference to top item on the stack.
00263     const_iterator begin() const;
00264     //! Reference one past bottom item on the stack.
00265     iterator end();
00266     //! Reference one past bottom item on the stack.
00267     const_iterator end() const;
00268 
00269     // Logging support.
00270 
00271     /** Base class for erratum sink.
00272         When an errata is abandoned, this will be called on it to perform
00273         any client specific logging. It is passed around by handle so that
00274         it doesn't have to support copy semantics (and is not destructed
00275         until application shutdown). Clients can subclass this class in order
00276         to preserve arbitrary data for the sink or retain a handle to the
00277         sink for runtime modifications.
00278      */
00279     class Sink : public IntrusivePtrCounter {
00280     public:
00281         typedef Sink self; ///< Self reference type.
00282         typedef IntrusivePtr<self> Handle;  ///< Handle type.
00283 
00284         /// Handle an abandoned errata.
00285         virtual void operator() (Errata const&) const = 0;
00286         /// Force virtual destructor.
00287         virtual ~Sink() {}
00288     };
00289 
00290     //! Register a sink for discarded erratum.
00291     static void registerSink(Sink::Handle const& s);
00292 
00293     /// Register a function as a sink.
00294     typedef void (*SinkHandlerFunction)(Errata const&);
00295 
00296     // Wrapper class to support registering functions as sinks.
00297     struct SinkFunctionWrapper : public Sink {
00298         /// Constructor.
00299         SinkFunctionWrapper(SinkHandlerFunction f) : m_f(f) { }
00300         /// Operator to invoke the function.
00301         virtual void operator() (Errata const& e) const { m_f(e); }
00302         SinkHandlerFunction m_f; ///< Client supplied handler.
00303     };
00304 
00305     /// Register a sink function for abandonded erratum.
00306     static void registerSink(SinkHandlerFunction f) {
00307         registerSink(Sink::Handle(new SinkFunctionWrapper(f)));
00308     }
00309 
00310     /** Simple formatted output.
00311 
00312         Each message is written to a line. All lines are indented with
00313         whitespace @a offset characters. Lines are indented an
00314         additional @a indent. This value is increased by @a shift for
00315         each level of nesting of an @c Errata. if @a lead is not @c
00316         NULL the indentation is overwritten by @a lead if @a indent is
00317         non-zero. It acts as a "continuation" marker for nested
00318         @c Errata.
00319         
00320      */
00321     std::ostream& write(
00322       std::ostream& out, ///< Output stream.
00323       int offset, ///< Lead white space for every line.
00324       int indent, ///< Additional indention per line for messages.
00325       int shift, ///< Additional @a indent for nested @c Errata.
00326       char const* lead ///< Leading text for nested @c Errata.
00327     ) const;
00328     /// Simple formatted output to fixed sized buffer.
00329     /// @return Number of characters written to @a buffer.
00330     size_t write(
00331       char* buffer, ///< Output buffer.
00332       size_t n, ///< Buffer size.
00333       int offset, ///< Lead white space for every line.
00334       int indent, ///< Additional indention per line for messages.
00335       int shift, ///< Additional @a indent for nested @c Errata.
00336       char const* lead ///< Leading text for nested @c Errata.
00337     ) const;
00338 
00339 # if USING_BOOST
00340     /// Functor type for sink.
00341     typedef boost::function<void (Errata const&)> SinkFunctor;
00342 
00343     // Wrapper class to support registering functions as sinks.
00344     struct SinkFunctorWrapper : public Sink {
00345         /// Constructor.
00346         SinkFunctionWrapper(SinkHandlerFunctor f) : m_f(f) { }
00347         /// Operator to invoke the function.
00348         virtual void operator() (Errata const& e) const { m_f(e); }
00349         SinkHandlerFunctor m_f; ///< Client supplied handler.
00350     };
00351 
00352     /// Register a sink function for abandonded erratum.
00353     static void registerSink(SinkFunctor const& f) {
00354         registerSink(Sink::Handle(new SinkFunctorWrapper(f)));
00355     }
00356 
00357     /// Generate formatted output.
00358     /// For each message in the stack, invoke @c boost::format passing
00359     /// @a fmt as the format string and the message ID and message text as
00360     /// two values. It is not an error to elide either or both. @a glue is
00361     /// sent to the stream @a s between every pair of messages.
00362     /// @return The stream @a s.
00363     std::ostream& format(
00364         std::ostream& s,           ///< Output stream
00365         boost::format const& fmt,  ///< Format string
00366         std::string const& glue = DEFAULT_GLUE ///< Glue
00367     ) const;
00368 
00369     /// Generate formatted output.
00370     /// A convenience overload so clients do not have to include the Boost.Format headers.
00371     /// @return The formatted output.
00372     /// @see std::ostream& format ( std::ostream& s, boost::format const& fmt, std::string const& glue ).
00373     std::ostream& format(
00374         std::ostream& s,           ///< Output stream
00375         std::string const& fmt,    ///< Format string
00376         std::string const& glue = DEFAULT_GLUE ///< Glue
00377     ) const;
00378 
00379     /// Generate formatted output.
00380     /// For each message in the stack, invoke @c boost::format passing
00381     /// @a fmt as the format string and the message ID and message text as
00382     /// two values. It is not an error to elide either or both. @a glue is
00383     /// added between every pair of messages.
00384     /// @note This is identical to the stream variant except the output
00385     /// is put in a string instead of a stream.
00386     /// @return The formatted output.
00387     /// @see std::ostream& format ( std::ostream& s, boost::format const& fmt, std::string const& glue ).
00388     std::string format(
00389         boost::format const& fmt,  ///< Format string
00390         std::string const& glue = DEFAULT_GLUE ///< Glue
00391     ) const;
00392 
00393     /// Generate formatted output.
00394     /// A convenience overload so clients do not have to include the Boost.Format headers.
00395     /// @return The formatted output.
00396     /// @see std::string format ( boost::format const& fmt, std::string const& glue ).
00397     std::string format(
00398         std::string const& fmt,  ///< Format string
00399         std::string const& glue = DEFAULT_GLUE ///< Glue
00400     ) const;
00401 # endif // USING_BOOST
00402 
00403 protected:
00404     /// Construct from implementation pointer.
00405     /// Used internally by nested classes.
00406     Errata(ImpPtr const& ptr);
00407     /// Implementation instance.
00408     ImpPtr m_data;
00409 
00410     /// Return the implementation instance, allocating and unsharing as needed.
00411     Data* pre_write();
00412     /// Force and return an implementation instance.
00413     /// Does not follow copy on write.
00414     Data* instance();
00415 
00416     /// Used for returns when no data is present.
00417     static Message const NIL_MESSAGE;
00418 
00419     friend struct Data;
00420     friend class Item;
00421 
00422 };
00423 
00424 extern std::ostream& operator<< (std::ostream& os, Errata const& stat);
00425 
00426 /// Storage for a single message.
00427 struct Errata::Message {
00428   typedef Message self; ///< Self reference type.
00429 
00430   /// Default constructor.
00431   /// The message has Id = 0, default code,  and empty text.
00432   Message();
00433 
00434   /// Construct from text.
00435   /// Id is zero and Code is default.
00436   Message(
00437     std::string const& text ///< Finalized message text.
00438   );
00439 
00440   /// Construct with @a id and @a text.
00441   /// Code is default.
00442   Message(
00443     Id id, ///< ID of message in table.
00444     std::string const& text ///< Final text for message.
00445   );
00446 
00447   /// Construct with @a id, @a code, and @a text.
00448   Message(
00449     Id id, ///< Message Id.
00450     Code code, ///< Message Code.
00451     std::string const& text ///< Final text for message.
00452   );
00453 
00454   /// Reset to the message to default state.
00455   self& clear();
00456 
00457   /// Set the message Id.
00458   self& set(
00459     Id id ///< New message Id.
00460   );
00461 
00462   /// Set the code.
00463   self& set(
00464     Code code ///< New code for message.
00465   );
00466 
00467   /// Set the text.
00468   self& set(
00469     std::string const& text ///< New message text.
00470   );
00471 
00472   /// Set the text.
00473   self& set(
00474     char const* text ///< New message text.
00475   );
00476 
00477   /// Set the errata.
00478   self& set(
00479     Errata const& err ///< Errata to store.
00480   );
00481 
00482   /// Get the text of the message.
00483   std::string const& text() const;
00484 
00485   /// Get the code.
00486   Code getCode() const;
00487   /// Get the nested status.
00488   /// @return A status object, which is not @c NULL if there is a
00489   /// nested status stored in this item.
00490   Errata getErrata() const;
00491 
00492   /** The default message code.
00493 
00494       This value is used as the Code value for constructing and
00495       clearing messages. It can be changed to control the value
00496       used for empty messages.
00497   */
00498   static Code Default_Code;
00499 
00500   /// Type for overriding success message test.
00501   typedef bool (*SuccessTest)(Message const& m);
00502 
00503   /** Success message test.
00504 
00505       When a message is tested for being "successful", this
00506       function is called. It may be overridden by a client.
00507       The initial value is @c DEFAULT_SUCCESS_TEST.
00508 
00509       @note This is only called when there are Messages in the
00510       Errata. An empty Errata (@c NULL or empty stack) is always
00511       a success. Only the @c top Message is checked.
00512 
00513       @return @c true if the message indicates success,
00514       @c false otherwise.
00515   */
00516   static SuccessTest Success_Test;
00517 
00518   /// Indicate success if the message code is zero.
00519   /// @note Used as the default success test.
00520   static bool isCodeZero(Message const& m);
00521 
00522   static SuccessTest const DEFAULT_SUCCESS_TEST;
00523 
00524   Id m_id; ///< Message ID.
00525   Code m_code; ///< Message code.
00526   std::string m_text; ///< Final text.
00527   Errata m_errata; ///< Nested errata.
00528 };
00529 
00530 /** This is the implementation class for Errata.
00531 
00532     It holds the actual messages and is treated as a passive data
00533     object with nice constructors.
00534 
00535     We implement reference counting semantics by hand for two
00536     reasons. One is that we need to do some specialized things, but
00537     mainly because the client can't see this class so we can't
00538 */
00539 struct Errata::Data : public IntrusivePtrCounter {
00540   typedef Data self; ///< Self reference type.
00541 
00542   //! Default constructor.
00543   Data();
00544 
00545   /// Destructor, to do logging.
00546   ~Data();
00547 
00548   //! Number of messages.
00549   size_t size() const;
00550 
00551   /// Get the top message on the stack.
00552   Message const& top() const;
00553 
00554   /// Put a message on top of the stack.
00555   void push(Message const& msg);
00556 
00557   /// Log this when it is deleted.
00558   bool m_log_on_delete;
00559 
00560   //! The message stack.
00561   Container m_items;
00562 };
00563 
00564 /// Forward iterator for @c Messages in an @c Errata.
00565 class Errata::iterator : public Errata::Container::reverse_iterator {
00566 public:
00567     typedef iterator self; ///< Self reference type.
00568     typedef Errata::Container::reverse_iterator super; ///< Parent type.
00569     iterator(); ///< Default constructor.
00570     /// Copy constructor.
00571     iterator(
00572         self const& that ///< Source instance.
00573     );
00574     /// Construct from super class.
00575     iterator(
00576         super const& that ///< Source instance.
00577     );
00578     /// Assignment.
00579     self& operator = (self const& that);
00580     /// Assignment from super class.
00581     self& operator = (super const& that);
00582     /// Prefix increment.
00583     self& operator ++ ();
00584     /// Prefix decrement.
00585     self& operator -- ();
00586 };
00587 
00588 /// Forward constant iterator for @c Messages in an @c Errata.
00589 class Errata::const_iterator : public Errata::Container::const_reverse_iterator {
00590 public:
00591     typedef const_iterator self; ///< Self reference type.
00592     typedef Errata::Container::const_reverse_iterator super; ///< Parent type.
00593     const_iterator(); ///< Default constructor.
00594     /// Copy constructor.
00595     const_iterator(
00596         self const& that ///< Source instance.
00597     );
00598     const_iterator(
00599         super const& that ///< Source instance.
00600     );
00601     /// Assignment.
00602     self& operator = (self const& that);
00603     /// Assignment from super class.
00604     self& operator = (super const& that);
00605     /// Prefix increment.
00606     self& operator ++ ();
00607     /// Prefix decrement.
00608     self& operator -- ();
00609 };
00610 
00611 /** Helper class for @c Rv.
00612     This class enables us to move the implementation of non-templated methods
00613     and members out of the header file for a cleaner API.
00614  */
00615 struct RvBase {
00616   Errata _errata;    ///< The status from the function.
00617 
00618   /** Default constructor. */
00619   RvBase();
00620 
00621   /** Construct with specific status.
00622    */
00623   RvBase (
00624     Errata const& s ///< Status to copy
00625   );
00626 
00627   //! Test the return value for success.
00628   bool isOK() const;
00629 
00630   /** Clear any stacked errors.
00631       This is useful during shutdown, to silence irrelevant errors caused
00632       by the shutdown process.
00633   */
00634   void clear();
00635 
00636   /// Inhibit logging of the errata.
00637   void doNotLog();
00638 };
00639 
00640 /** Return type for returning a value and status (errata).  In
00641     general, a method wants to return both a result and a status so
00642     that errors are logged properly. This structure is used to do that
00643     in way that is more usable than just @c std::pair.  - Simpler and
00644     shorter typography - Force use of @c errata rather than having to
00645     remember it (and the order) each time - Enable assignment directly
00646     to @a R for ease of use and compatibility so clients can upgrade
00647     asynchronously.
00648  */
00649 template < typename R >
00650 struct Rv : public RvBase {
00651   typedef Rv self;       ///< Standard self reference type.
00652   typedef RvBase super; ///< Standard super class reference type.
00653   typedef R Result; ///< Type of result value.
00654 
00655   Result _result;             ///< The actual result of the function.
00656 
00657   /** Default constructor.
00658       The default constructor for @a R is used.
00659       The status is initialized to SUCCESS.
00660   */
00661   Rv();
00662 
00663   /** Standard (success) constructor.
00664 
00665       This copies the result and sets the status to SUCCESS.
00666 
00667       @note Not @c explicit so that clients can return just a result
00668        and have it be marked as SUCCESS.
00669    */
00670   Rv(
00671     Result const& r  ///< The function result
00672   );
00673 
00674   /** Construct from a result and a pre-existing status object.
00675 
00676       @internal No constructor from just an Errata to avoid
00677       potential ambiguity with constructing from result type.
00678    */
00679   Rv(
00680     Result const& r,         ///< The function result
00681     Errata const& s    ///< A pre-existing status object
00682   );
00683 
00684   /** User conversion to the result type.
00685 
00686       This makes it easy to use the function normally or to pass the
00687       result only to other functions without having to extract it by
00688       hand.
00689   */
00690   operator Result const& () const;
00691 
00692   /** Assignment from result type.
00693 
00694       This allows the result to be assigned to a pre-declared return
00695       value structure.  The return value is a reference to the
00696       internal result so that this operator can be chained in other
00697       assignments to instances of result type. This is most commonly
00698       used when the result is computed in to a local variable to be
00699       both returned and stored in a member.
00700 
00701       @code
00702       Rv<int> zret;
00703       int value;
00704       // ... complex computations, result in value
00705       this->m_value = zret = value;
00706       // ...
00707       return zret;
00708       @endcode
00709 
00710       @return A reference to the copy of @a r stored in this object.
00711   */
00712   Result& operator = (
00713     Result const& r  ///< Result to assign
00714   ) {
00715     _result = r;
00716     return _result;
00717   }
00718 
00719   /** Add the status from another instance to this one.
00720       @return A reference to @c this object.
00721   */
00722   template < typename U >
00723   self& push(
00724     Rv<U> const& that ///< Source of status messages
00725   );
00726 
00727   /** Set the result.
00728 
00729       This differs from assignment of the function result in that the
00730       return value is a reference to the @c Rv, not the internal
00731       result. This makes it useful for assigning a result local
00732       variable and then returning.
00733 
00734       @code
00735       Rv<int> zret;
00736       int value;
00737       // ... complex computation, result in value
00738       return zret.set(value);
00739       @endcode
00740   */
00741   self& set(
00742     Result const& r  ///< Result to store
00743   );
00744 
00745   /** Return the result.
00746       @return A reference to the result value in this object.
00747   */
00748   Result& result();
00749 
00750   /** Return the result.
00751       @return A reference to the result value in this object.
00752   */
00753   Result const& result() const;
00754 
00755   /** Return the status.
00756       @return A reference to the @c errata in this object.
00757   */
00758   Errata& errata();
00759 
00760   /** Return the status.
00761       @return A reference to the @c errata in this object.
00762   */
00763   Errata const& errata() const;
00764 
00765   /// Directly set the errata
00766   self& operator = (
00767     Errata const& status ///< Errata to assign.
00768   );
00769 
00770   /// Push a message on to the status.
00771   self& push(
00772     Errata::Message const& msg
00773   );
00774 };
00775 
00776 /** Combine a function result and status in to an @c Rv.
00777     This is useful for clients that want to declare the status object
00778     and result independently.
00779  */
00780 template < typename R > Rv<R>
00781 MakeRv(
00782   R const& r,          ///< The function result
00783   Errata const& s      ///< The pre-existing status object
00784 ) {
00785     return Rv<R>(r, s);
00786 }
00787 /* ----------------------------------------------------------------------- */
00788 /* ----------------------------------------------------------------------- */
00789 // Inline methods.
00790 inline Errata::Message::Message()
00791   : m_id(0), m_code(Default_Code) {
00792 }
00793 inline Errata::Message::Message(std::string const& text)
00794   : m_id(0), m_code(Default_Code), m_text(text) {
00795 }
00796 inline Errata::Message::Message(Id id, std::string const& text)
00797   : m_id(id), m_code(Default_Code), m_text(text) {
00798 }
00799 inline Errata::Message::Message(Id id, Code code, std::string const& text)
00800   : m_id(id), m_code(code), m_text(text) {
00801 }
00802 inline Errata::Message& Errata::Message::clear() {
00803   m_id = 0;
00804   m_code = Default_Code;
00805   m_text.erase();
00806   m_errata.clear();
00807   return *this;
00808 }
00809 
00810 inline std::string const& Errata::Message::text() const { return m_text; }
00811 inline Errata::Code Errata::Message::getCode() const { return m_code; }
00812 inline Errata Errata::Message::getErrata() const { return m_errata; }
00813 
00814 inline Errata::Message& Errata::Message::set(Id id) {
00815   m_id = id;
00816   return *this;
00817 }
00818 inline Errata::Message& Errata::Message::set(Code code) {
00819   m_code = code;
00820   return *this;
00821 }
00822 inline Errata::Message& Errata::Message::set(std::string const& text) {
00823   m_text = text;
00824   return *this;
00825 }
00826 inline Errata::Message& Errata::Message::set(char const* text) {
00827   m_text = text;
00828   return *this;
00829 }
00830 inline Errata::Message& Errata::Message::set(Errata const& err) {
00831   m_errata = err;
00832   m_errata.doNotLog();
00833   return *this;
00834 }
00835 
00836 inline Errata::Errata(Id id, Code code, std::string const& text) {
00837   this->push(Message(id, code, text));
00838 }
00839 inline Errata::Errata(Message const& msg) {
00840   this->push(msg);
00841 }
00842 
00843 inline Errata::operator bool() const { return this->isOK(); }
00844 
00845 inline size_t Errata::size() const {
00846   return m_data ? m_data->m_items.size() : 0;
00847 }
00848 
00849 inline bool Errata::isOK() const {
00850   return 0 == m_data
00851     || 0 == m_data->size()
00852     || Message::Success_Test(this->top())
00853     ;
00854 }
00855 
00856 inline Errata&
00857 Errata::push(std::string const& text) {
00858   this->push(Message(text));
00859   return *this;
00860 }
00861 
00862 inline Errata&
00863 Errata::push(Id id, std::string const& text) {
00864   this->push(Message(id, text));
00865   return *this;
00866 }
00867 
00868 inline Errata&
00869 Errata::push(Id id, Code code, std::string const& text) {
00870   this->push(Message(id, code, text));
00871   return *this;
00872 }
00873 
00874 inline Errata::Message const&
00875 Errata::top() const {
00876   return m_data ? m_data->top() : NIL_MESSAGE;
00877 }
00878 inline Errata& Errata::doNotLog() {
00879   this->instance()->m_log_on_delete = false;
00880   return *this;
00881 }
00882 
00883 inline Errata::Data::Data() : m_log_on_delete(true) {}
00884 inline size_t Errata::Data::size() const { return m_items.size(); }
00885 
00886 inline Errata::iterator::iterator() { }
00887 inline Errata::iterator::iterator(self const& that) : super(that) { }
00888 inline Errata::iterator::iterator(super const& that) : super(that) { }
00889 inline Errata::iterator& Errata::iterator::operator = (self const& that) { this->super::operator = (that); return *this; }
00890 inline Errata::iterator& Errata::iterator::operator = (super const& that) { this->super::operator = (that); return *this; }
00891 inline Errata::iterator& Errata::iterator::operator ++ () { this->super::operator ++ (); return *this; }
00892 inline Errata::iterator& Errata::iterator::operator -- () { this->super::operator -- (); return *this; }
00893 
00894 inline Errata::const_iterator::const_iterator() { }
00895 inline Errata::const_iterator::const_iterator(self const& that) : super(that) { }
00896 inline Errata::const_iterator::const_iterator(super const& that) : super(that) { }
00897 inline Errata::const_iterator& Errata::const_iterator::operator = (self const& that) { super::operator = (that); return *this; }
00898 inline Errata::const_iterator& Errata::const_iterator::operator = (super const& that) { super::operator = (that); return *this; }
00899 inline Errata::const_iterator& Errata::const_iterator::operator ++ () { this->super::operator ++ (); return *this; }
00900 inline Errata::const_iterator& Errata::const_iterator::operator -- () { this->super::operator -- (); return *this; }
00901 
00902 inline RvBase::RvBase() { }
00903 inline RvBase::RvBase(Errata const& errata) : _errata(errata) { }
00904 inline bool RvBase::isOK() const { return _errata; }
00905 inline void RvBase::clear() { _errata.clear(); }
00906 inline void RvBase::doNotLog() { _errata.doNotLog(); }
00907 
00908 template < typename T > Rv<T>::Rv() { }
00909 template < typename T > Rv<T>::Rv(Result const& r) : _result(r) { }
00910 template < typename T > Rv<T>::Rv(Result const& r, Errata const& errata)
00911   : super(errata)
00912   , _result(r) {
00913 }
00914 template < typename T > Rv<T>::operator Result const&() const {
00915   return _result;
00916 }
00917 template < typename T > T const& Rv<T>::result() const { return _result; }
00918 template < typename T > T& Rv<T>::result() { return _result; }
00919 template < typename T > Errata const& Rv<T>::errata() const { return _errata; }
00920 template < typename T > Errata& Rv<T>::errata() { return _errata; }
00921 template < typename T > Rv<T>&
00922 Rv<T>::set(Result const& r) {
00923   _result = r;
00924   return *this;
00925 }
00926 template < typename T > Rv<T>&
00927 Rv<T>::operator = (Errata const& errata) {
00928   _errata = errata;
00929   return *this;
00930 }
00931 template < typename T > Rv<T>&
00932 Rv<T>::push(Errata::Message const& msg) {
00933   _errata.push(msg);
00934   return *this;
00935 }
00936 template < typename T > template < typename U > Rv<T>&
00937 Rv<T>::push(Rv<U> const& that) {
00938   _errata.push(that.errata());
00939   return *this;
00940 }
00941 /* ----------------------------------------------------------------------- */
00942 /* ----------------------------------------------------------------------- */
00943 } // namespace ts
00944 
00945 # endif // TS_ERRATA_HEADER

Generated by  doxygen 1.7.1