1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8/*
9 * Error codes used by gmmain.cpp.
10 */
11
12#ifndef gm_error_DEFINED
13#define gm_error_DEFINED
14
15#include "gm.h"
16
17namespace skiagm {
18
19    /**
20     * The complete list of error types we might encounter in GM.
21     */
22    enum ErrorType {
23        // Even though kNoGpuContext_ErrorType only occurs when SK_SUPPORT_GPU
24        // is turned on, we always include this type in our enum so that
25        // reports will be consistent whether SK_SUPPORT_GPU is turned on
26        // or off (as long as the number of these errors is 0).
27        kNoGpuContext_ErrorType,
28
29        kIntentionallySkipped_ErrorType,
30        kRenderModeMismatch_ErrorType,
31        kGeneratePdfFailed_ErrorType,
32        kExpectationsMismatch_ErrorType,
33        kMissingExpectations_ErrorType,
34        kWritingReferenceImage_ErrorType,
35        kLast_ErrorType = kWritingReferenceImage_ErrorType
36    };
37
38    /**
39     * Returns the name of the given ErrorType.
40     */
41    static const char *getErrorTypeName(ErrorType type) {
42        switch(type) {
43        case kNoGpuContext_ErrorType:
44            return "NoGpuContext";
45        case kIntentionallySkipped_ErrorType:
46            return "IntentionallySkipped";
47        case kRenderModeMismatch_ErrorType:
48            return "RenderModeMismatch";
49        case kGeneratePdfFailed_ErrorType:
50            return "GeneratePdfFailed";
51        case kExpectationsMismatch_ErrorType:
52            return "ExpectationsMismatch";
53        case kMissingExpectations_ErrorType:
54            return "MissingExpectations";
55        case kWritingReferenceImage_ErrorType:
56            return "WritingReferenceImage";
57        }
58        // control should never reach here
59        SkDEBUGFAIL("getErrorTypeName() called with unknown type");
60        return "Unknown";
61    }
62
63    /**
64     * Fills in "type" with the ErrorType associated with name "name".
65     * Returns true if we found one, false if it is an unknown type name.
66     */
67    static bool getErrorTypeByName(const char name[], ErrorType *type) {
68        for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
69            ErrorType thisType = static_cast<ErrorType>(typeInt);
70            const char *thisTypeName = getErrorTypeName(thisType);
71            if (0 == strcmp(thisTypeName, name)) {
72                *type = thisType;
73                return true;
74            }
75        }
76        return false;
77    }
78
79    /**
80     * A combination of 0 or more ErrorTypes.
81     */
82    class ErrorCombination {
83    public:
84        ErrorCombination() : fBitfield(0) {}
85        ErrorCombination(const ErrorType type) : fBitfield(1 << type) {}
86
87        /**
88         * Returns true iff there are NO errors.
89         */
90        bool isEmpty() const {
91            return (0 == this->fBitfield);
92        }
93
94        /**
95         * Adds this ErrorType to this ErrorCombination.
96         */
97        void add(const ErrorType type) {
98            this->fBitfield |= (1 << type);
99        }
100
101        /**
102         * Adds all ErrorTypes in "other" to this ErrorCombination.
103         */
104        void add(const ErrorCombination other) {
105            this->fBitfield |= other.fBitfield;
106        }
107
108        /**
109         * Returns true iff this ErrorCombination includes this ErrorType.
110         */
111        bool includes(const ErrorType type) const {
112            return !(0 == (this->fBitfield & (1 << type)));
113        }
114
115        /**
116         * Returns a string representation of all ErrorTypes in this
117         * ErrorCombination.
118         *
119         * @param separator text with which to separate ErrorType names
120         */
121        SkString asString(const char separator[]) const {
122            SkString s;
123            for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
124                ErrorType type = static_cast<ErrorType>(typeInt);
125                if (this->includes(type)) {
126                    if (!s.isEmpty()) {
127                        s.append(separator);
128                    }
129                    s.append(getErrorTypeName(type));
130                }
131            }
132            return s;
133        }
134
135        /**
136         * Returns a new ErrorCombination, which includes the union of all
137         * ErrorTypes in two ErrorCombination objects (this and other).
138         */
139        ErrorCombination plus(const ErrorCombination& other) const {
140            ErrorCombination retval;
141            retval.fBitfield = this->fBitfield | other.fBitfield;
142            return retval;
143        }
144
145        /**
146         * Returns a new ErrorCombination, which is a copy of "this"
147         * but with all ErrorTypes in "other" removed.
148         */
149        ErrorCombination minus(const ErrorCombination& other) const {
150            ErrorCombination retval;
151            retval.fBitfield = this->fBitfield & ~(other.fBitfield);
152            return retval;
153        }
154
155    private:
156        int fBitfield;
157    };
158
159    // No errors at all.
160    const static ErrorCombination kEmpty_ErrorCombination;
161}
162
163#endif // ifndef gm_error_DEFINED
164