1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 2009-2011, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 *******************************************************************************
8 *   file name:  errorcode.h
9 *   encoding:   US-ASCII
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 *   created on: 2009mar10
14 *   created by: Markus W. Scherer
15 */
16 
17 #ifndef __ERRORCODE_H__
18 #define __ERRORCODE_H__
19 
20 /**
21  * \file
22  * \brief C++ API: ErrorCode class intended to make it easier to use
23  *                 ICU C and C++ APIs from C++ user code.
24  */
25 
26 #include "unicode/utypes.h"
27 #include "unicode/uobject.h"
28 
29 U_NAMESPACE_BEGIN
30 
31 /**
32  * Wrapper class for UErrorCode, with conversion operators for direct use
33  * in ICU C and C++ APIs.
34  * Intended to be used as a base class, where a subclass overrides
35  * the handleFailure() function so that it throws an exception,
36  * does an assert(), logs an error, etc.
37  * This is not an abstract base class. This class can be used and instantiated
38  * by itself, although it will be more useful when subclassed.
39  *
40  * Features:
41  * - The constructor initializes the internal UErrorCode to U_ZERO_ERROR,
42  *   removing one common source of errors.
43  * - Same use in C APIs taking a UErrorCode * (pointer)
44  *   and C++ taking UErrorCode & (reference) via conversion operators.
45  * - Possible automatic checking for success when it goes out of scope.
46  *
47  * Note: For automatic checking for success in the destructor, a subclass
48  * must implement such logic in its own destructor because the base class
49  * destructor cannot call a subclass function (like handleFailure()).
50  * The ErrorCode base class destructor does nothing.
51  *
52  * Note also: While it is possible for a destructor to throw an exception,
53  * it is generally unsafe to do so. This means that in a subclass the destructor
54  * and the handleFailure() function may need to take different actions.
55  *
56  * Sample code:
57  * \code
58  *   class IcuErrorCode: public icu::ErrorCode {
59  *   public:
60  *     virtual ~IcuErrorCode() {  // should be defined in .cpp as "key function"
61  *       // Safe because our handleFailure() does not throw exceptions.
62  *       if(isFailure()) { handleFailure(); }
63  *     }
64  *   protected:
65  *     virtual void handleFailure() const {
66  *       log_failure(u_errorName(errorCode));
67  *       exit(errorCode);
68  *     }
69  *   };
70  *   IcuErrorCode error_code;
71  *   UConverter *cnv = ucnv_open("Shift-JIS", error_code);
72  *   length = ucnv_fromUChars(dest, capacity, src, length, error_code);
73  *   ucnv_close(cnv);
74  *   // IcuErrorCode destructor checks for success.
75  * \endcode
76  *
77  * @stable ICU 4.2
78  */
79 class U_COMMON_API ErrorCode: public UMemory {
80 public:
81     /**
82      * Default constructor. Initializes its UErrorCode to U_ZERO_ERROR.
83      * @stable ICU 4.2
84      */
ErrorCode()85     ErrorCode() : errorCode(U_ZERO_ERROR) {}
86     /** Destructor, does nothing. See class documentation for details. @stable ICU 4.2 */
87     virtual ~ErrorCode();
88     /** Conversion operator, returns a reference. @stable ICU 4.2 */
89     operator UErrorCode & () { return errorCode; }
90     /** Conversion operator, returns a pointer. @stable ICU 4.2 */
91     operator UErrorCode * () { return &errorCode; }
92     /** Tests for U_SUCCESS(). @stable ICU 4.2 */
isSuccess()93     UBool isSuccess() const { return U_SUCCESS(errorCode); }
94     /** Tests for U_FAILURE(). @stable ICU 4.2 */
isFailure()95     UBool isFailure() const { return U_FAILURE(errorCode); }
96     /** Returns the UErrorCode value. @stable ICU 4.2 */
get()97     UErrorCode get() const { return errorCode; }
98     /** Sets the UErrorCode value. @stable ICU 4.2 */
set(UErrorCode value)99     void set(UErrorCode value) { errorCode=value; }
100     /** Returns the UErrorCode value and resets it to U_ZERO_ERROR. @stable ICU 4.2 */
101     UErrorCode reset();
102     /**
103      * Asserts isSuccess().
104      * In other words, this method checks for a failure code,
105      * and the base class handles it like this:
106      * \code
107      *   if(isFailure()) { handleFailure(); }
108      * \endcode
109      * @stable ICU 4.4
110      */
111     void assertSuccess() const;
112     /**
113      * Return a string for the UErrorCode value.
114      * The string will be the same as the name of the error code constant
115      * in the UErrorCode enum.
116      * @stable ICU 4.4
117      */
118     const char* errorName() const;
119 
120 protected:
121     /**
122      * Internal UErrorCode, accessible to subclasses.
123      * @stable ICU 4.2
124      */
125     UErrorCode errorCode;
126     /**
127      * Called by assertSuccess() if isFailure() is true.
128      * A subclass should override this function to deal with a failure code:
129      * Throw an exception, log an error, terminate the program, or similar.
130      * @stable ICU 4.2
131      */
handleFailure()132     virtual void handleFailure() const {}
133 };
134 
135 U_NAMESPACE_END
136 
137 #endif  // __ERRORCODE_H__
138