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