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