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 void printAll(const char *fname = NULL) const; 78 void printNonDefault(const char *fname = NULL) const; 79 const char *configFileLocation() const; 80 void possiblyDumpFile() const; 81 void validate() const; 82 template <typename T> void set(const char *confname, 83 T value, 84 bool warnIfNotFound = true); 85 #ifdef SK_SUPPORT_UNITTEST 86 static void UnitTest(); 87 #endif 88 private: 89 template<typename T> friend class SkRTConf; 90 91 void registerConf(SkRTConfBase *conf); 92 template <typename T> bool parse(const char *name, T* value); 93 94 SkTDArray<SkString *> fConfigFileKeys, fConfigFileValues; 95 typedef SkTDict< SkTDArray<SkRTConfBase *> * > ConfMap; 96 ConfMap fConfs; 97 #ifdef SK_SUPPORT_UNITTEST 98 SkRTConfRegistry(bool); 99 #endif 100 }; 101 102 // our singleton registry 103 104 SkRTConfRegistry &skRTConfRegistry(); 105 106 template<typename T> 107 SkRTConf<T>::SkRTConf(const char *name, const T &defaultValue, const char *description) 108 : SkRTConfBase(name) 109 , fValue(defaultValue) 110 , fDefault(defaultValue) 111 , fDescription(description) { 112 113 T value; 114 if (skRTConfRegistry().parse(fName.c_str(), &value)) { 115 fValue = value; 116 } 117 skRTConfRegistry().registerConf(this); 118 } 119 120 template<typename T> 121 void SkRTConf<T>::print(SkWStream *o) const { 122 char outline[200]; // should be ok because we specify a max. width for everything here. 123 char *outptr; 124 if (strlen(getName()) >= 30) { 125 o->writeText(getName()); 126 o->writeText(" "); 127 outptr = &(outline[0]); 128 } else { 129 sprintf(outline, "%-30.30s", getName()); 130 outptr = &(outline[30]); 131 } 132 133 doPrint(outptr); 134 sprintf(outptr+30, " %.128s", fDescription.c_str()); 135 for (size_t i = strlen(outline); i --> 0 && ' ' == outline[i];) { 136 outline[i] = '\0'; 137 } 138 o->writeText(outline); 139 } 140 141 template<typename T> 142 void SkRTConf<T>::doPrint(char *s) const { 143 sprintf(s, "%-30.30s", "How do I print myself??"); 144 } 145 146 template<> inline void SkRTConf<bool>::doPrint(char *s) const { 147 char tmp[30]; 148 sprintf(tmp, "%s # [%s]", fValue ? "true" : "false", fDefault ? "true" : "false"); 149 sprintf(s, "%-30.30s", tmp); 150 } 151 152 template<> inline void SkRTConf<int>::doPrint(char *s) const { 153 char tmp[30]; 154 sprintf(tmp, "%d # [%d]", fValue, fDefault); 155 sprintf(s, "%-30.30s", tmp); 156 } 157 158 template<> inline void SkRTConf<unsigned int>::doPrint(char *s) const { 159 char tmp[30]; 160 sprintf(tmp, "%u # [%u]", fValue, fDefault); 161 sprintf(s, "%-30.30s", tmp); 162 } 163 164 template<> inline void SkRTConf<float>::doPrint(char *s) const { 165 char tmp[30]; 166 sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); 167 sprintf(s, "%-30.30s", tmp); 168 } 169 170 template<> inline void SkRTConf<double>::doPrint(char *s) const { 171 char tmp[30]; 172 sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); 173 sprintf(s, "%-30.30s", tmp); 174 } 175 176 template<> inline void SkRTConf<const char *>::doPrint(char *s) const { 177 char tmp[30]; 178 sprintf(tmp, "%s # [%s]", fValue, fDefault); 179 sprintf(s, "%-30.30s", tmp); 180 } 181 182 template<typename T> 183 bool SkRTConf<T>::equals(const SkRTConfBase *conf) const { 184 // static_cast here is okay because there's only one kind of child class. 185 const SkRTConf<T> *child_pointer = static_cast<const SkRTConf<T> *>(conf); 186 return child_pointer && 187 fName == child_pointer->fName && 188 fDescription == child_pointer->fDescription && 189 fValue == child_pointer->fValue && 190 fDefault == child_pointer->fDefault; 191 } 192 193 #endif 194