xref: /trafficserver/include/tscore/Errata.h (revision 4f8cb034)
1 /** @file
2     Stacking error message handling.
3 
4     The problem addressed by this library is the ability to pass back
5     detailed error messages from failures. It is hard to get good
6     diagnostics because the specific failures and general context are
7     located in very different stack frames. This library allows local
8     functions to pass back local messages which can be easily
9     augmented as the error travels up the stack frame.
10 
11     This could be done with exceptions but
12     - That is more effort to implemention
13     - Generally more expensive.
14 
15     Each message on a stack contains text and a numeric identifier.
16     The identifier value zero is reserved for messages that are not
17     errors so that information can be passed back even in the success
18     case.
19 
20     The implementation takes the position that success is fast and
21     failure is expensive. Therefore it is optimized for the success
22     path, imposing very little overhead. On the other hand, if an
23     error occurs and is handled, that is generally so expensive that
24     optimizations are pointless (although, of course, one should not
25     be gratuitiously expensive).
26 
27     The library also provides the @c Rv ("return value") template to
28     make returning values and status easier. This template allows a
29     function to return a value and status pair with minimal changes.
30     The pair acts like the value type in most situations, while
31     providing access to the status.
32 
33     Each instance of an erratum is a wrapper class that emulates value
34     semantics (copy on write). This means passing even large message
35     stacks is inexpensive, involving only a pointer copy and reference
36     counter increment and decrement. A success value is represented by
37     an internal @c NULL so it is even cheaper to copy.
38 
39     To further ease use, the library has the ability to define @a
40     sinks.  A sink is a function that acts on an erratum when it
41     becomes unreferenced. The indended use is to send the messages to
42     an output log. This makes reporting errors to a log from even
43     deeply nested functions easy while preserving the ability of the
44     top level logic to control such logging.
45 
46     @section license License
47 
48     Licensed to the Apache Software Foundation (ASF) under one
49     or more contributor license agreements.  See the NOTICE file
50     distributed with this work for additional information
51     regarding copyright ownership.  The ASF licenses this file
52     to you under the Apache License, Version 2.0 (the
53     "License"); you may not use this file except in compliance
54     with the License.  You may obtain a copy of the License at
55 
56     http://www.apache.org/licenses/LICENSE-2.0
57 
58     Unless required by applicable law or agreed to in writing, software
59     distributed under the License is distributed on an "AS IS" BASIS,
60     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
61     See the License for the specific language governing permissions and
62     limitations under the License.
63  */
64 
65 #pragma once
66 
67 #include <memory>
68 #include <string>
69 #include <iosfwd>
70 #include <sstream>
71 #include <deque>
72 #include "NumericType.h"
73 #include "IntrusivePtr.h"
74 
75 namespace ts
76 {
77 /** Class to hold a stack of error messages (the "errata").
78     This is a smart handle class, which wraps the actual data
79     and can therefore be treated a value type with cheap copy
80     semantics. Default construction is very cheap.
81  */
82 class Errata
83 {
84 protected:
85   /// Implementation class.
86   struct Data;
87   /// Handle for implementation class instance.
88   typedef IntrusivePtr<Data> ImpPtr;
89 
90 public:
91   typedef Errata self; /// Self reference type.
92 
93   /// Message ID.
94   typedef NumericType<unsigned int, struct MsgIdTag> Id;
95 
96   /* Tag / level / code severity.
97      This is intended for clients to use to provide additional
98      classification of a message. A severity code, as for syslog,
99      is a common use.
100 
101   */
102   typedef NumericType<unsigned int, struct CodeTag> Code;
103   struct Message;
104 
105   typedef std::deque<Message> Container; ///< Storage type for messages.
106   // We iterate backwards to look like a stack.
107   //    typedef Container::reverse_iterator iterator; ///< Message iteration.
108   /// Message const iteration.
109   //    typedef Container::const_reverse_iterator const_iterator;
110   /// Reverse message iteration.
111   //    typedef Container::iterator reverse_iterator;
112   /// Reverse constant message iteration.
113   //    typedef Container::const_iterator const_reverse_iterator;
114 
115   /// Default constructor - empty errata, very fast.
116   Errata();
117   /// Copy constructor, very fast.
118   Errata(self const &that ///< Object to copy
119   );
120   /// Construct from string.
121   /// Message Id and Code are default.
122   explicit Errata(std::string const &text ///< Finalized message text.
123   );
124   /// Construct with @a id and @a text.
125   /// Code is default.
126   Errata(Id id,                  ///< Message id.
127          std::string const &text ///< Message text.
128   );
129   /// Construct with @a id, @a code, and @a text.
130   Errata(Id id,                  ///< Message text.
131          Code code,              ///< Message code.
132          std::string const &text ///< Message text.
133   );
134   /** Construct from a message instance.
135       This is equivalent to default constructing an @c errata and then
136       invoking @c push with an argument of @a msg.
137   */
138   Errata(Message const &msg ///< Message to push
139   );
140 
141   /// Move constructor.
142   Errata(self &&that);
143   /// Move constructor from @c Message.
144   Errata(Message &&msg);
145 
146   /// destructor
147   ~Errata();
148 
149   /// Self assignment.
150   /// @return A reference to this object.
151   self &operator=(const self &that ///< Source instance.
152   );
153 
154   /// Move assignment.
155   self &operator=(self &&that);
156 
157   /** Assign message.
158       All other messages are discarded.
159       @return A reference to this object.
160   */
161   self &operator=(Message const &msg ///< Source message.
162   );
163 
164   /** Push @a text as a message.
165       The message is constructed from just the @a text.
166       It becomes the top message.
167       @return A reference to this object.
168   */
169   self &push(std::string const &text);
170   /** Push @a text as a message with message @a id.
171       The message is constructed from @a text and @a id.
172       It becomes the top message.
173       @return A reference to this object.
174   */
175   self &push(Id id, std::string const &text);
176   /** Push @a text as a message with message @a id and @a code.
177       The message is constructed from @a text and @a id.
178       It becomes the top message.
179       @return A reference to this object.
180   */
181   self &push(Id id, Code code, std::string const &text);
182   /** Push a message.
183       @a msg becomes the top message.
184       @return A reference to this object.
185   */
186   self &push(Message const &msg);
187   self &push(Message &&msg);
188 
189   /** Push a constructed @c Message.
190       The @c Message is set to have the @a id and @a code. The other arguments are converted
191       to strings and concatenated to form the messsage text.
192       @return A reference to this object.
193   */
194   template <typename... Args> self &push(Id id, Code code, Args const &... args);
195 
196   /** Push a nested status.
197       @a err becomes the top item.
198       @return A reference to this object.
199   */
200   self &push(self const &err);
201 
202   /** Access top message.
203       @return If the errata is empty, a default constructed message
204       otherwise the most recent message.
205    */
206   Message const &top() const;
207 
208   /** Move messages from @a that to @c this errata.
209       Messages from @a that are put on the top of the
210       stack in @c this and removed from @a that.
211   */
212   self &pull(self &that);
213 
214   /// Remove last message.
215   void pop();
216 
217   /// Remove all messages.
218   void clear();
219 
220   /** Inhibit logging.
221       @note This only affects @c this as a top level @c errata.
222       It has no effect on this @c this being logged as a nested
223       @c errata.
224   */
225   self &doNotLog();
226 
227   friend std::ostream &operator<<(std::ostream &, self const &);
228 
229   /// Default glue value (a newline) for text rendering.
230   static std::string const DEFAULT_GLUE;
231 
232   /** Test status.
233 
234       Equivalent to @c success but more convenient for use in
235       control statements.
236 
237       @return @c true if no messages or last message has a zero
238       message ID, @c false otherwise.
239    */
240   operator bool() const;
241 
242   /** Test errata for no failure condition.
243 
244       Equivalent to @c operator @c bool but easier to invoke.
245 
246       @return @c true if no messages or last message has a zero
247       message ID, @c false otherwise.
248    */
249   bool isOK() const;
250 
251   /// Number of messages in the errata.
252   size_t size() const;
253 
254   /*  Forward declares.
255       We have to make our own iterators as the least bad option. The problem
256       is that we have recursive structures so declaration order is difficult.
257       We can't use the container iterators here because the element type is
258       not yet defined. If we define the element type here, it can't contain
259       an Errata and we have to do funky things to get around that. So we
260       have our own iterators, which are just shadowing sublclasses of the
261       container iterators.
262    */
263   class iterator;
264   class const_iterator;
265 
266   /// Reference to top item on the stack.
267   iterator begin();
268   /// Reference to top item on the stack.
269   const_iterator begin() const;
270   //! Reference one past bottom item on the stack.
271   iterator end();
272   //! Reference one past bottom item on the stack.
273   const_iterator end() const;
274 
275   // Logging support.
276 
277   /** Base class for erratum sink.
278       When an errata is abandoned, this will be called on it to perform
279       any client specific logging. It is passed around by handle so that
280       it doesn't have to support copy semantics (and is not destructed
281       until application shutdown). Clients can subclass this class in order
282       to preserve arbitrary data for the sink or retain a handle to the
283       sink for runtime modifications.
284    */
285   class Sink : public IntrusivePtrCounter
286   {
287   public:
288     typedef Sink self;                 ///< Self reference type.
289     typedef IntrusivePtr<self> Handle; ///< Handle type.
290 
291     /// Handle an abandoned errata.
292     virtual void operator()(Errata const &) const = 0;
293     /// Force virtual destructor.
~Sink()294     virtual ~Sink() {}
295   };
296 
297   //! Register a sink for discarded erratum.
298   static void registerSink(Sink::Handle const &s);
299 
300   /// Register a function as a sink.
301   typedef void (*SinkHandlerFunction)(Errata const &);
302 
303   // Wrapper class to support registering functions as sinks.
304   struct SinkFunctionWrapper : public Sink {
305     /// Constructor.
SinkFunctionWrapperts::Errata::SinkFunctionWrapper306     SinkFunctionWrapper(SinkHandlerFunction f) : m_f(f) {}
307     /// Operator to invoke the function.
308     void
operator ()ts::Errata::SinkFunctionWrapper309     operator()(Errata const &e) const override
310     {
311       m_f(e);
312     }
313     SinkHandlerFunction m_f; ///< Client supplied handler.
314   };
315 
316   /// Register a sink function for abandonded erratum.
317   static void
registerSink(SinkHandlerFunction f)318   registerSink(SinkHandlerFunction f)
319   {
320     registerSink(Sink::Handle(new SinkFunctionWrapper(f)));
321   }
322 
323   /** Simple formatted output.
324 
325       Each message is written to a line. All lines are indented with
326       whitespace @a offset characters. Lines are indented an
327       additional @a indent. This value is increased by @a shift for
328       each level of nesting of an @c Errata. if @a lead is not @c
329       NULL the indentation is overwritten by @a lead if @a indent is
330       non-zero. It acts as a "continuation" marker for nested
331       @c Errata.
332 
333    */
334   std::ostream &write(std::ostream &out, ///< Output stream.
335                       int offset,        ///< Lead white space for every line.
336                       int indent,        ///< Additional indention per line for messages.
337                       int shift,         ///< Additional @a indent for nested @c Errata.
338                       char const *lead   ///< Leading text for nested @c Errata.
339   ) const;
340   /// Simple formatted output to fixed sized buffer.
341   /// @return Number of characters written to @a buffer.
342   size_t write(char *buffer,    ///< Output buffer.
343                size_t n,        ///< Buffer size.
344                int offset,      ///< Lead white space for every line.
345                int indent,      ///< Additional indention per line for messages.
346                int shift,       ///< Additional @a indent for nested @c Errata.
347                char const *lead ///< Leading text for nested @c Errata.
348   ) const;
349 
350 protected:
351   /// Construct from implementation pointer.
352   /// Used internally by nested classes.
353   Errata(ImpPtr const &ptr);
354   /// Implementation instance.
355   ImpPtr m_data;
356 
357   /// Return the implementation instance, allocating and unsharing as needed.
358   Data *pre_write();
359   /// Force and return an implementation instance.
360   /// Does not follow copy on write.
361   Data const *instance();
362 
363   /// Used for returns when no data is present.
364   static Message const NIL_MESSAGE;
365 
366   friend struct Data;
367   friend class Item;
368 };
369 
370 extern std::ostream &operator<<(std::ostream &os, Errata const &stat);
371 
372 /// Storage for a single message.
373 struct Errata::Message {
374   typedef Message self; ///< Self reference type.
375 
376   /// Default constructor.
377   /// The message has Id = 0, default code,  and empty text.
378   Message() = default;
379 
380   /// Construct from text.
381   /// Id is zero and Code is default.
382   Message(std::string const &text ///< Finalized message text.
383   );
384 
385   /// Construct with @a id and @a text.
386   /// Code is default.
387   Message(Id id,                  ///< ID of message in table.
388           std::string const &text ///< Final text for message.
389   );
390 
391   /// Construct with @a id, @a code, and @a text.
392   Message(Id id,                  ///< Message Id.
393           Code code,              ///< Message Code.
394           std::string const &text ///< Final text for message.
395   );
396 
397   /// Construct with an @a id, @a code, and a @a message.
398   /// The message contents are created by converting the variable arguments
399   /// to strings using the stream operator and concatenated in order.
400   template <typename... Args>
401   Message(Id id,     ///< Message Id.
402           Code code, ///< Message Code.
403           Args const &... text);
404 
405   /// Reset to the message to default state.
406   self &clear();
407 
408   /// Set the message Id.
409   self &set(Id id ///< New message Id.
410   );
411 
412   /// Set the code.
413   self &set(Code code ///< New code for message.
414   );
415 
416   /// Set the text.
417   self &set(std::string const &text ///< New message text.
418   );
419 
420   /// Set the text.
421   self &set(char const *text ///< New message text.
422   );
423 
424   /// Set the errata.
425   self &set(Errata const &err ///< Errata to store.
426   );
427 
428   /// Get the text of the message.
429   std::string const &text() const;
430 
431   /// Get the code.
432   Code getCode() const;
433   /// Get the nested status.
434   /// @return A status object, which is not @c NULL if there is a
435   /// nested status stored in this item.
436   Errata getErrata() const;
437 
438   /** The default message code.
439 
440       This value is used as the Code value for constructing and
441       clearing messages. It can be changed to control the value
442       used for empty messages.
443   */
444   static Code Default_Code;
445 
446   /// Type for overriding success message test.
447   typedef bool (*SuccessTest)(Message const &m);
448 
449   /** Success message test.
450 
451       When a message is tested for being "successful", this
452       function is called. It may be overridden by a client.
453       The initial value is @c DEFAULT_SUCCESS_TEST.
454 
455       @note This is only called when there are Messages in the
456       Errata. An empty Errata (@c NULL or empty stack) is always
457       a success. Only the @c top Message is checked.
458 
459       @return @c true if the message indicates success,
460       @c false otherwise.
461   */
462   static SuccessTest Success_Test;
463 
464   /// Indicate success if the message code is zero.
465   /// @note Used as the default success test.
466   static bool isCodeZero(Message const &m);
467 
468   static SuccessTest const DEFAULT_SUCCESS_TEST;
469 
470   template <typename... Args> static std::string stringify(Args const &... items);
471 
472   Id m_id     = 0;            ///< Message ID.
473   Code m_code = Default_Code; ///< Message code.
474   std::string m_text;         ///< Final text.
475   Errata m_errata;            ///< Nested errata.
476 };
477 
478 /** This is the implementation class for Errata.
479 
480     It holds the actual messages and is treated as a passive data
481     object with nice constructors.
482 
483     We implement reference counting semantics by hand for two
484     reasons. One is that we need to do some specialized things, but
485     mainly because the client can't see this class so we can't
486 */
487 struct Errata::Data : public IntrusivePtrCounter {
488   typedef Data self; ///< Self reference type.
489 
490   //! Default constructor.
491   Data();
492 
493   /// Destructor, to do logging.
494   ~Data();
495 
496   //! Number of messages.
497   size_t size() const;
498 
499   /// Get the top message on the stack.
500   Message const &top() const;
501 
502   /// Put a message on top of the stack.
503   void push(Message const &msg);
504   void push(Message &&msg);
505 
506   /// Log this when it is deleted.
507   mutable bool m_log_on_delete = true;
508 
509   //! The message stack.
510   Container m_items;
511 };
512 
513 /// Forward iterator for @c Messages in an @c Errata.
514 class Errata::iterator : public Errata::Container::reverse_iterator
515 {
516 public:
517   typedef iterator self;                             ///< Self reference type.
518   typedef Errata::Container::reverse_iterator super; ///< Parent type.
519   iterator();                                        ///< Default constructor.
520   /// Copy constructor.
521   iterator(self const &that ///< Source instance.
522   );
523   /// Construct from super class.
524   iterator(super const &that ///< Source instance.
525   );
526   /// Assignment.
527   self &operator=(self const &that);
528   /// Assignment from super class.
529   self &operator=(super const &that);
530   /// Prefix increment.
531   self &operator++();
532   /// Prefix decrement.
533   self &operator--();
534 };
535 
536 /// Forward constant iterator for @c Messages in an @c Errata.
537 class Errata::const_iterator : public Errata::Container::const_reverse_iterator
538 {
539 public:
540   typedef const_iterator self;                             ///< Self reference type.
541   typedef Errata::Container::const_reverse_iterator super; ///< Parent type.
542   const_iterator();                                        ///< Default constructor.
543   /// Copy constructor.
544   const_iterator(self const &that ///< Source instance.
545   );
546   const_iterator(super const &that ///< Source instance.
547   );
548   /// Assignment.
549   self &operator=(self const &that);
550   /// Assignment from super class.
551   self &operator=(super const &that);
552   /// Prefix increment.
553   self &operator++();
554   /// Prefix decrement.
555   self &operator--();
556 };
557 
558 /** Helper class for @c Rv.
559     This class enables us to move the implementation of non-templated methods
560     and members out of the header file for a cleaner API.
561  */
562 struct RvBase {
563   Errata _errata; ///< The status from the function.
564 
565   /** Default constructor. */
566   RvBase();
567 
568   /** Construct with specific status.
569    */
570   RvBase(Errata const &s ///< Status to copy
571   );
572 
573   //! Test the return value for success.
574   bool isOK() const;
575 
576   /** Clear any stacked errors.
577       This is useful during shutdown, to silence irrelevant errors caused
578       by the shutdown process.
579   */
580   void clear();
581 
582   /// Inhibit logging of the errata.
583   void doNotLog();
584 };
585 
586 /** Return type for returning a value and status (errata).  In
587     general, a method wants to return both a result and a status so
588     that errors are logged properly. This structure is used to do that
589     in way that is more usable than just @c std::pair.  - Simpler and
590     shorter typography - Force use of @c errata rather than having to
591     remember it (and the order) each time - Enable assignment directly
592     to @a R for ease of use and compatibility so clients can upgrade
593     asynchronously.
594  */
595 template <typename R> struct Rv : public RvBase {
596   typedef Rv self;      ///< Standard self reference type.
597   typedef RvBase super; ///< Standard super class reference type.
598   typedef R Result;     ///< Type of result value.
599 
600   Result _result; ///< The actual result of the function.
601 
602   /** Default constructor.
603       The default constructor for @a R is used.
604       The status is initialized to SUCCESS.
605   */
606   Rv();
607 
608   /** Standard (success) constructor.
609 
610       This copies the result and sets the status to SUCCESS.
611 
612       @note Not @c explicit so that clients can return just a result
613        and have it be marked as SUCCESS.
614    */
615   Rv(Result const &r ///< The function result
616   );
617 
618   /** Construct from a result and a pre-existing status object.
619 
620       @internal No constructor from just an Errata to avoid
621       potential ambiguity with constructing from result type.
622    */
623   Rv(Result const &r, ///< The function result
624      Errata const &s  ///< A pre-existing status object
625   );
626 
627   /** User conversion to the result type.
628 
629       This makes it easy to use the function normally or to pass the
630       result only to other functions without having to extract it by
631       hand.
632   */
633   operator Result const &() const;
634 
635   /** Assignment from result type.
636 
637       This allows the result to be assigned to a pre-declared return
638       value structure.  The return value is a reference to the
639       internal result so that this operator can be chained in other
640       assignments to instances of result type. This is most commonly
641       used when the result is computed in to a local variable to be
642       both returned and stored in a member.
643 
644       @code
645       Rv<int> zret;
646       int value;
647       // ... complex computations, result in value
648       this->m_value = zret = value;
649       // ...
650       return zret;
651       @endcode
652 
653       @return A reference to the copy of @a r stored in this object.
654   */
655   Result &
operator =ts::Rv656   operator=(Result const &r ///< Result to assign
657   )
658   {
659     _result = r;
660     return _result;
661   }
662 
663   /** Add the status from another instance to this one.
664       @return A reference to @c this object.
665   */
666   template <typename U>
667   self &push(Rv<U> const &that ///< Source of status messages
668   );
669 
670   /** Set the result.
671 
672       This differs from assignment of the function result in that the
673       return value is a reference to the @c Rv, not the internal
674       result. This makes it useful for assigning a result local
675       variable and then returning.
676 
677       @code
678       Rv<int> zret;
679       int value;
680       // ... complex computation, result in value
681       return zret.set(value);
682       @endcode
683   */
684   self &set(Result const &r ///< Result to store
685   );
686 
687   /** Return the result.
688       @return A reference to the result value in this object.
689   */
690   Result &result();
691 
692   /** Return the result.
693       @return A reference to the result value in this object.
694   */
695   Result const &result() const;
696 
697   /** Return the status.
698       @return A reference to the @c errata in this object.
699   */
700   Errata &errata();
701 
702   /** Return the status.
703       @return A reference to the @c errata in this object.
704   */
705   Errata const &errata() const;
706 
707   /// Directly set the errata
708   self &operator=(Errata const &status ///< Errata to assign.
709   );
710 
711   /// Push a message on to the status.
712   self &push(Errata::Message const &msg);
713 };
714 
715 /** Combine a function result and status in to an @c Rv.
716     This is useful for clients that want to declare the status object
717     and result independently.
718  */
719 template <typename R>
720 Rv<R>
MakeRv(R const & r,Errata const & s)721 MakeRv(R const &r,     ///< The function result
722        Errata const &s ///< The pre-existing status object
723 )
724 {
725   return Rv<R>(r, s);
726 }
727 /* ----------------------------------------------------------------------- */
728 /* ----------------------------------------------------------------------- */
729 // Inline methods.
Message(std::string const & text)730 inline Errata::Message::Message(std::string const &text) : m_text(text) {}
Message(Id id,std::string const & text)731 inline Errata::Message::Message(Id id, std::string const &text) : m_text(text) {}
Message(Id id,Code code,std::string const & text)732 inline Errata::Message::Message(Id id, Code code, std::string const &text) : m_text(text) {}
733 template <typename... Args>
Message(Id id,Code code,Args const &...text)734 Errata::Message::Message(Id id, Code code, Args const &... text) : m_id(id), m_code(code), m_text(stringify(text...))
735 {
736 }
737 
738 inline Errata::Message &
clear()739 Errata::Message::clear()
740 {
741   m_id   = 0;
742   m_code = Default_Code;
743   m_text.erase();
744   m_errata.clear();
745   return *this;
746 }
747 
748 inline std::string const &
text() const749 Errata::Message::text() const
750 {
751   return m_text;
752 }
753 inline Errata::Code
getCode() const754 Errata::Message::getCode() const
755 {
756   return m_code;
757 }
758 inline Errata
getErrata() const759 Errata::Message::getErrata() const
760 {
761   return m_errata;
762 }
763 
764 inline Errata::Message &
set(Id id)765 Errata::Message::set(Id id)
766 {
767   m_id = id;
768   return *this;
769 }
770 inline Errata::Message &
set(Code code)771 Errata::Message::set(Code code)
772 {
773   m_code = code;
774   return *this;
775 }
776 inline Errata::Message &
set(std::string const & text)777 Errata::Message::set(std::string const &text)
778 {
779   m_text = text;
780   return *this;
781 }
782 inline Errata::Message &
set(char const * text)783 Errata::Message::set(char const *text)
784 {
785   m_text = text;
786   return *this;
787 }
788 inline Errata::Message &
set(Errata const & err)789 Errata::Message::set(Errata const &err)
790 {
791   m_errata = err;
792   m_errata.doNotLog();
793   return *this;
794 }
795 
796 template <typename... Args>
797 std::string
stringify(Args const &...items)798 Errata::Message::stringify(Args const &... items)
799 {
800   std::ostringstream s;
801   (void)(int[]){0, ((s << items), 0)...};
802   return s.str();
803 }
804 
Errata()805 inline Errata::Errata() {}
Errata(Id id,Code code,std::string const & text)806 inline Errata::Errata(Id id, Code code, std::string const &text)
807 {
808   this->push(Message(id, code, text));
809 }
Errata(Message const & msg)810 inline Errata::Errata(Message const &msg)
811 {
812   this->push(msg);
813 }
Errata(Message && msg)814 inline Errata::Errata(Message &&msg)
815 {
816   this->push(std::move(msg));
817 }
818 
819 inline Errata::operator bool() const
820 {
821   return this->isOK();
822 }
823 
824 inline size_t
size() const825 Errata::size() const
826 {
827   return m_data ? m_data->m_items.size() : 0;
828 }
829 
830 inline bool
isOK() const831 Errata::isOK() const
832 {
833   return nullptr == m_data || 0 == m_data->size() || Message::Success_Test(this->top());
834 }
835 
836 inline Errata &
push(std::string const & text)837 Errata::push(std::string const &text)
838 {
839   this->push(Message(text));
840   return *this;
841 }
842 
843 inline Errata &
push(Id id,std::string const & text)844 Errata::push(Id id, std::string const &text)
845 {
846   this->push(Message(id, text));
847   return *this;
848 }
849 
850 inline Errata &
push(Id id,Code code,std::string const & text)851 Errata::push(Id id, Code code, std::string const &text)
852 {
853   this->push(Message(id, code, text));
854   return *this;
855 }
856 
857 template <typename... Args>
858 auto
push(Id id,Code code,Args const &...args)859 Errata::push(Id id, Code code, Args const &... args) -> self &
860 {
861   this->push(Message(id, code, args...));
862   return *this;
863 }
864 
865 inline Errata::Message const &
top() const866 Errata::top() const
867 {
868   return m_data ? m_data->top() : NIL_MESSAGE;
869 }
870 inline Errata &
doNotLog()871 Errata::doNotLog()
872 {
873   this->instance()->m_log_on_delete = false;
874   return *this;
875 }
876 
Data()877 inline Errata::Data::Data() {}
878 inline size_t
size() const879 Errata::Data::size() const
880 {
881   return m_items.size();
882 }
883 
iterator()884 inline Errata::iterator::iterator() {}
iterator(self const & that)885 inline Errata::iterator::iterator(self const &that) : super(that) {}
iterator(super const & that)886 inline Errata::iterator::iterator(super const &that) : super(that) {}
887 inline Errata::iterator &
operator =(self const & that)888 Errata::iterator::operator=(self const &that)
889 {
890   this->super::operator=(that);
891   return *this;
892 }
893 inline Errata::iterator &
operator =(super const & that)894 Errata::iterator::operator=(super const &that)
895 {
896   this->super::operator=(that);
897   return *this;
898 }
899 inline Errata::iterator &
operator ++()900 Errata::iterator::operator++()
901 {
902   this->super::operator++();
903   return *this;
904 }
905 inline Errata::iterator &
operator --()906 Errata::iterator::operator--()
907 {
908   this->super::operator--();
909   return *this;
910 }
911 
const_iterator()912 inline Errata::const_iterator::const_iterator() {}
const_iterator(self const & that)913 inline Errata::const_iterator::const_iterator(self const &that) : super(that) {}
const_iterator(super const & that)914 inline Errata::const_iterator::const_iterator(super const &that) : super(that) {}
915 inline Errata::const_iterator &
operator =(self const & that)916 Errata::const_iterator::operator=(self const &that)
917 {
918   super::operator=(that);
919   return *this;
920 }
921 inline Errata::const_iterator &
operator =(super const & that)922 Errata::const_iterator::operator=(super const &that)
923 {
924   super::operator=(that);
925   return *this;
926 }
927 inline Errata::const_iterator &
operator ++()928 Errata::const_iterator::operator++()
929 {
930   this->super::operator++();
931   return *this;
932 }
933 inline Errata::const_iterator &
operator --()934 Errata::const_iterator::operator--()
935 {
936   this->super::operator--();
937   return *this;
938 }
939 
RvBase()940 inline RvBase::RvBase() {}
RvBase(Errata const & errata)941 inline RvBase::RvBase(Errata const &errata) : _errata(errata) {}
942 inline bool
isOK() const943 RvBase::isOK() const
944 {
945   return _errata;
946 }
947 inline void
clear()948 RvBase::clear()
949 {
950   _errata.clear();
951 }
952 inline void
doNotLog()953 RvBase::doNotLog()
954 {
955   _errata.doNotLog();
956 }
957 
Rv()958 template <typename T> Rv<T>::Rv() : _result() {}
Rv(Result const & r)959 template <typename T> Rv<T>::Rv(Result const &r) : _result(r) {}
Rv(Result const & r,Errata const & errata)960 template <typename T> Rv<T>::Rv(Result const &r, Errata const &errata) : super(errata), _result(r) {}
961 template <typename T> Rv<T>::operator Result const &() const
962 {
963   return _result;
964 }
965 template <typename T>
966 T const &
result() const967 Rv<T>::result() const
968 {
969   return _result;
970 }
971 template <typename T>
972 T &
result()973 Rv<T>::result()
974 {
975   return _result;
976 }
977 template <typename T>
978 Errata const &
errata() const979 Rv<T>::errata() const
980 {
981   return _errata;
982 }
983 template <typename T>
984 Errata &
errata()985 Rv<T>::errata()
986 {
987   return _errata;
988 }
989 template <typename T>
990 Rv<T> &
set(Result const & r)991 Rv<T>::set(Result const &r)
992 {
993   _result = r;
994   return *this;
995 }
996 template <typename T>
997 Rv<T> &
operator =(Errata const & errata)998 Rv<T>::operator=(Errata const &errata)
999 {
1000   _errata = errata;
1001   return *this;
1002 }
1003 template <typename T>
1004 Rv<T> &
push(Errata::Message const & msg)1005 Rv<T>::push(Errata::Message const &msg)
1006 {
1007   _errata.push(msg);
1008   return *this;
1009 }
1010 template <typename T>
1011 template <typename U>
1012 Rv<T> &
push(Rv<U> const & that)1013 Rv<T>::push(Rv<U> const &that)
1014 {
1015   _errata.push(that.errata());
1016   return *this;
1017 }
1018 /* ----------------------------------------------------------------------- */
1019 /* ----------------------------------------------------------------------- */
1020 } // namespace ts
1021