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 #ifndef SkRTConf_DEFINED 10 #define SkRTConf_DEFINED 11 12 #include "SkString.h" 13 #include "SkStream.h" 14 15 #include "SkTDict.h" 16 #include "SkTArray.h" 17 18 /** \class SkRTConfBase 19 Non-templated base class for the runtime configs 20 */ 21 22 class SkRTConfBase { 23 public: 24 SkRTConfBase(const char *name) : fName(name) {} 25 virtual ~SkRTConfBase() {} 26 virtual const char *getName() const { return fName.c_str(); } 27 virtual bool isDefault() const = 0; 28 virtual void print(SkWStream *o) const = 0; 29 virtual bool equals(const SkRTConfBase *conf) const = 0; 30 protected: 31 SkString fName; 32 }; 33 34 /** \class SkRTConf 35 A class to provide runtime configurability. 36 */ 37 template<typename T> class SkRTConf: public SkRTConfBase { 38 public: 39 SkRTConf(const char *name, const T &defaultValue, const char *description); 40 operator const T&() const { return fValue; } 41 void print(SkWStream *o) const; 42 bool equals(const SkRTConfBase *conf) const; 43 bool isDefault() const { return fDefault == fValue; } 44 void set(const T& value) { fValue = value; } 45 protected: 46 void doPrint(char *s) const; 47 48 T fValue; 49 T fDefault; 50 SkString fDescription; 51 }; 52 53 #ifdef SK_DEVELOPER 54 #define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static SkRTConf<confType> varName(confName, defaultValue, description) 55 #define SK_CONF_SET(confname, value) \ 56 skRTConfRegistry().set(confname, value, true) 57 /* SK_CONF_TRY_SET() is like SK_CONF_SET(), but doesn't complain if 58 confname can't be found. This is useful if the SK_CONF_DECLARE is 59 inside a source file whose linkage is dependent on the system. */ 60 #define SK_CONF_TRY_SET(confname, value) \ 61 skRTConfRegistry().set(confname, value, false) 62 #else 63 #define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static confType varName = defaultValue 64 #define SK_CONF_SET(confname, value) (void) confname, (void) value 65 #define SK_CONF_TRY_SET(confname, value) (void) confname, (void) value 66 #endif 67 68 /** \class SkRTConfRegistry 69 A class that maintains a systemwide registry of all runtime configuration 70 parameters. Mainly used for printing them out and handling multiply-defined 71 knobs. 72 */ 73 74 class SkRTConfRegistry { 75 public: 76 SkRTConfRegistry(); 77 ~SkRTConfRegistry(); 78 void printAll(const char *fname = NULL) const; 79 bool hasNonDefault() const; 80 void printNonDefault(const char *fname = NULL) const; 81 const char *configFileLocation() const; 82 void possiblyDumpFile() const; 83 void validate() const; 84 template <typename T> void set(const char *confname, 85 T value, 86 bool warnIfNotFound = true); 87 #ifdef SK_SUPPORT_UNITTEST 88 static void UnitTest(); 89 #endif 90 private: 91 template<typename T> friend class SkRTConf; 92 93 void registerConf(SkRTConfBase *conf); 94 template <typename T> bool parse(const char *name, T* value); 95 96 SkTDArray<SkString *> fConfigFileKeys, fConfigFileValues; 97 typedef SkTDict< SkTDArray<SkRTConfBase *> * > ConfMap; 98 ConfMap fConfs; 99 #ifdef SK_SUPPORT_UNITTEST 100 SkRTConfRegistry(bool); 101 #endif 102 }; 103 104 // our singleton registry 105 106 SkRTConfRegistry &skRTConfRegistry(); 107 108 template<typename T> 109 SkRTConf<T>::SkRTConf(const char *name, const T &defaultValue, const char *description) 110 : SkRTConfBase(name) 111 , fValue(defaultValue) 112 , fDefault(defaultValue) 113 , fDescription(description) { 114 115 T value; 116 if (skRTConfRegistry().parse(fName.c_str(), &value)) { 117 fValue = value; 118 } 119 skRTConfRegistry().registerConf(this); 120 } 121 122 template<typename T> 123 void SkRTConf<T>::print(SkWStream *o) const { 124 char outline[200]; // should be ok because we specify a max. width for everything here. 125 char *outptr; 126 if (strlen(getName()) >= 30) { 127 o->writeText(getName()); 128 o->writeText(" "); 129 outptr = &(outline[0]); 130 } else { 131 sprintf(outline, "%-30.30s", getName()); 132 outptr = &(outline[30]); 133 } 134 135 doPrint(outptr); 136 sprintf(outptr+30, " %.128s", fDescription.c_str()); 137 for (size_t i = strlen(outline); i --> 0 && ' ' == outline[i];) { 138 outline[i] = '\0'; 139 } 140 o->writeText(outline); 141 } 142 143 template<typename T> 144 void SkRTConf<T>::doPrint(char *s) const { 145 sprintf(s, "%-30.30s", "How do I print myself??"); 146 } 147 148 template<> inline void SkRTConf<bool>::doPrint(char *s) const { 149 char tmp[30]; 150 sprintf(tmp, "%s # [%s]", fValue ? "true" : "false", fDefault ? "true" : "false"); 151 sprintf(s, "%-30.30s", tmp); 152 } 153 154 template<> inline void SkRTConf<int>::doPrint(char *s) const { 155 char tmp[30]; 156 sprintf(tmp, "%d # [%d]", fValue, fDefault); 157 sprintf(s, "%-30.30s", tmp); 158 } 159 160 template<> inline void SkRTConf<unsigned int>::doPrint(char *s) const { 161 char tmp[30]; 162 sprintf(tmp, "%u # [%u]", fValue, fDefault); 163 sprintf(s, "%-30.30s", tmp); 164 } 165 166 template<> inline void SkRTConf<float>::doPrint(char *s) const { 167 char tmp[30]; 168 sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); 169 sprintf(s, "%-30.30s", tmp); 170 } 171 172 template<> inline void SkRTConf<double>::doPrint(char *s) const { 173 char tmp[30]; 174 sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); 175 sprintf(s, "%-30.30s", tmp); 176 } 177 178 template<> inline void SkRTConf<const char *>::doPrint(char *s) const { 179 char tmp[30]; 180 sprintf(tmp, "%s # [%s]", fValue, fDefault); 181 sprintf(s, "%-30.30s", tmp); 182 } 183 184 template<typename T> 185 bool SkRTConf<T>::equals(const SkRTConfBase *conf) const { 186 // static_cast here is okay because there's only one kind of child class. 187 const SkRTConf<T> *child_pointer = static_cast<const SkRTConf<T> *>(conf); 188 return child_pointer && 189 fName == child_pointer->fName && 190 fDescription == child_pointer->fDescription && 191 fValue == child_pointer->fValue && 192 fDefault == child_pointer->fDefault; 193 } 194 195 #endif 196