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        kExpectationsMismatch_ErrorType,
32        kMissingExpectations_ErrorType,
33        kWritingReferenceImage_ErrorType,
34        kLast_ErrorType = kWritingReferenceImage_ErrorType
35    };
36
37    /**
38     * Returns the name of the given ErrorType.
39     */
40    static const char *getErrorTypeName(ErrorType type) {
41        switch(type) {
42        case kNoGpuContext_ErrorType:
43            return "NoGpuContext";
44        case kIntentionallySkipped_ErrorType:
45            return "IntentionallySkipped";
46        case kRenderModeMismatch_ErrorType:
47            return "RenderModeMismatch";
48        case kExpectationsMismatch_ErrorType:
49            return "ExpectationsMismatch";
50        case kMissingExpectations_ErrorType:
51            return "MissingExpectations";
52        case kWritingReferenceImage_ErrorType:
53            return "WritingReferenceImage";
54        }
55        // control should never reach here
56        SkDEBUGFAIL("getErrorTypeName() called with unknown type");
57        return "Unknown";
58    }
59
60    /**
61     * Fills in "type" with the ErrorType associated with name "name".
62     * Returns true if we found one, false if it is an unknown type name.
63     */
64    static bool getErrorTypeByName(const char name[], ErrorType *type) {
65        for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
66            ErrorType thisType = static_cast<ErrorType>(typeInt);
67            const char *thisTypeName = getErrorTypeName(thisType);
68            if (0 == strcmp(thisTypeName, name)) {
69                *type = thisType;
70                return true;
71            }
72        }
73        return false;
74    }
75
76    /**
77     * A combination of 0 or more ErrorTypes.
78     */
79    class ErrorCombination {
80    public:
81        ErrorCombination() : fBitfield(0) {}
82        ErrorCombination(const ErrorType type) : fBitfield(1 << type) {}
83
84        /**
85         * Returns true iff there are NO errors.
86         */
87        bool isEmpty() const {
88            return (0 == this->fBitfield);
89        }
90
91        /**
92         * Adds this ErrorType to this ErrorCombination.
93         */
94        void add(const ErrorType type) {
95            this->fBitfield |= (1 << type);
96        }
97
98        /**
99         * Adds all ErrorTypes in "other" to this ErrorCombination.
100         */
101        void add(const ErrorCombination other) {
102            this->fBitfield |= other.fBitfield;
103        }
104
105        /**
106         * Returns true iff this ErrorCombination includes this ErrorType.
107         */
108        bool includes(const ErrorType type) const {
109            return !(0 == (this->fBitfield & (1 << type)));
110        }
111
112        /**
113         * Returns a string representation of all ErrorTypes in this
114         * ErrorCombination.
115         *
116         * @param separator text with which to separate ErrorType names
117         */
118        SkString asString(const char separator[]) const {
119            SkString s;
120            for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
121                ErrorType type = static_cast<ErrorType>(typeInt);
122                if (this->includes(type)) {
123                    if (!s.isEmpty()) {
124                        s.append(separator);
125                    }
126                    s.append(getErrorTypeName(type));
127                }
128            }
129            return s;
130        }
131
132        /**
133         * Returns a new ErrorCombination, which includes the union of all
134         * ErrorTypes in two ErrorCombination objects (this and other).
135         */
136        ErrorCombination plus(const ErrorCombination& other) const {
137            ErrorCombination retval;
138            retval.fBitfield = this->fBitfield | other.fBitfield;
139            return retval;
140        }
141
142        /**
143         * Returns a new ErrorCombination, which is a copy of "this"
144         * but with all ErrorTypes in "other" removed.
145         */
146        ErrorCombination minus(const ErrorCombination& other) const {
147            ErrorCombination retval;
148            retval.fBitfield = this->fBitfield & ~(other.fBitfield);
149            return retval;
150        }
151
152    private:
153        int fBitfield;
154    };
155
156    // No errors at all.
157    const static ErrorCombination kEmpty_ErrorCombination;
158}
159
160#endif // ifndef gm_error_DEFINED
161