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) skRTConfRegistry().set(confname, value) 56 #else 57 #define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static const confType varName = defaultValue 58 #define SK_CONF_SET(confname, value) (void) confname, (void) value 59 #endif 60 61 /** \class SkRTConfRegistry 62 A class that maintains a systemwide registry of all runtime configuration 63 parameters. Mainly used for printing them out and handling multiply-defined 64 knobs. 65 */ 66 67 class SkRTConfRegistry { 68 public: 69 SkRTConfRegistry(); 70 void printAll(const char *fname = NULL) const; 71 void printNonDefault(const char *fname = NULL) const; 72 const char *configFileLocation() const; 73 void possiblyDumpFile() const; 74 void validate() const; 75 template <typename T> void set(const char *confname, T value); 76 private: 77 template<typename T> friend class SkRTConf; 78 79 void registerConf(SkRTConfBase *conf); 80 template <typename T> bool parse(const char *name, T* value); 81 82 SkTDArray<SkString *> fConfigFileKeys, fConfigFileValues; 83 typedef SkTDict< SkTDArray<SkRTConfBase *> * > ConfMap; 84 ConfMap fConfs; 85 }; 86 87 // our singleton registry 88 89 SkRTConfRegistry &skRTConfRegistry(); 90 91 template<typename T> 92 SkRTConf<T>::SkRTConf(const char *name, const T &defaultValue, const char *description) 93 : SkRTConfBase(name) 94 , fValue(defaultValue) 95 , fDefault(defaultValue) 96 , fDescription(description) { 97 98 T value; 99 if (skRTConfRegistry().parse(fName.c_str(), &value)) { 100 fValue = value; 101 } 102 skRTConfRegistry().registerConf(this); 103 } 104 105 template<typename T> 106 void SkRTConf<T>::print(SkWStream *o) const { 107 char outline[200]; // should be ok because we specify a max. width for everything here. 108 109 sprintf(outline, "%-30.30s", getName()); 110 doPrint(&(outline[30])); 111 sprintf(&(outline[60]), " %.128s", fDescription.c_str()); 112 if (' ' == outline[strlen(outline)-1]) { 113 for (int i = strlen(outline)-1 ; ' ' == outline[i] ; i--) { 114 outline[i] = '\0'; 115 } 116 } 117 o->writeText(outline); 118 } 119 120 template<typename T> 121 void SkRTConf<T>::doPrint(char *s) const { 122 sprintf(s, "%-30.30s", "How do I print myself??"); 123 } 124 125 template<> inline void SkRTConf<bool>::doPrint(char *s) const { 126 char tmp[30]; 127 sprintf(tmp, "%s # [%s]", fValue ? "true" : "false", fDefault ? "true" : "false"); 128 sprintf(s, "%-30.30s", tmp); 129 } 130 131 template<> inline void SkRTConf<int>::doPrint(char *s) const { 132 char tmp[30]; 133 sprintf(tmp, "%d # [%d]", fValue, fDefault); 134 sprintf(s, "%-30.30s", tmp); 135 } 136 137 template<> inline void SkRTConf<unsigned int>::doPrint(char *s) const { 138 char tmp[30]; 139 sprintf(tmp, "%u # [%u]", fValue, fDefault); 140 sprintf(s, "%-30.30s", tmp); 141 } 142 143 template<> inline void SkRTConf<float>::doPrint(char *s) const { 144 char tmp[30]; 145 sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); 146 sprintf(s, "%-30.30s", tmp); 147 } 148 149 template<> inline void SkRTConf<double>::doPrint(char *s) const { 150 char tmp[30]; 151 sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); 152 sprintf(s, "%-30.30s", tmp); 153 } 154 155 template<> inline void SkRTConf<const char *>::doPrint(char *s) const { 156 char tmp[30]; 157 sprintf(tmp, "%s # [%s]", fValue, fDefault); 158 sprintf(s, "%-30.30s", tmp); 159 } 160 161 template<typename T> 162 bool SkRTConf<T>::equals(const SkRTConfBase *conf) const { 163 // static_cast here is okay because there's only one kind of child class. 164 const SkRTConf<T> *child_pointer = static_cast<const SkRTConf<T> *>(conf); 165 return child_pointer && 166 fName == child_pointer->fName && 167 fDescription == child_pointer->fDescription && 168 fValue == child_pointer->fValue && 169 fDefault == child_pointer->fDefault; 170 } 171 172 #endif 173