diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/utils/SkRTConf.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/utils/SkRTConf.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,350 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkRTConf.h" +#include "SkOSFile.h" + +SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) { + + SkFILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag); + + if (!fp) { + return; + } + + char line[1024]; + + while (!sk_feof(fp)) { + + if (!sk_fgets(line, sizeof(line), fp)) { + break; + } + + char *commentptr = strchr(line, '#'); + if (commentptr == line) { + continue; + } + if (NULL != commentptr) { + *commentptr = '\0'; + } + + char sep[] = " \t\r\n"; + + char *keyptr = strtok(line, sep); + if (!keyptr) { + continue; + } + + char *valptr = strtok(NULL, sep); + if (!valptr) { + continue; + } + + SkString* key = SkNEW_ARGS(SkString,(keyptr)); + SkString* val = SkNEW_ARGS(SkString,(valptr)); + + fConfigFileKeys.append(1, &key); + fConfigFileValues.append(1, &val); + } + sk_fclose(fp); +} + +SkRTConfRegistry::~SkRTConfRegistry() { + ConfMap::Iter iter(fConfs); + SkTDArray *confArray; + + while (iter.next(&confArray)) { + delete confArray; + } + + for (int i = 0 ; i < fConfigFileKeys.count() ; i++) { + SkDELETE(fConfigFileKeys[i]); + SkDELETE(fConfigFileValues[i]); + } +} + +const char *SkRTConfRegistry::configFileLocation() const { + return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever. +} + +// dump all known runtime config options to the file with their default values. +// to trigger this, make a config file of zero size. +void SkRTConfRegistry::possiblyDumpFile() const { + const char *path = configFileLocation(); + SkFILE *fp = sk_fopen(path, kRead_SkFILE_Flag); + if (!fp) { + return; + } + size_t configFileSize = sk_fgetsize(fp); + if (configFileSize == 0) { + printAll(path); + } + sk_fclose(fp); +} + +// Run through every provided configuration option and print a warning if the user hasn't +// declared a correponding configuration object somewhere. +void SkRTConfRegistry::validate() const { + for (int i = 0 ; i < fConfigFileKeys.count() ; i++) { + if (!fConfs.find(fConfigFileKeys[i]->c_str())) { + SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str()); + } + } +} + +void SkRTConfRegistry::printAll(const char *fname) const { + SkWStream *o; + + if (NULL != fname) { + o = new SkFILEWStream(fname); + } else { + o = new SkDebugWStream(); + } + + ConfMap::Iter iter(fConfs); + SkTDArray *confArray; + + while (iter.next(&confArray)) { + if (confArray->getAt(0)->isDefault()) { + o->writeText("# "); + } + confArray->getAt(0)->print(o); + o->newline(); + } + + delete o; +} + +bool SkRTConfRegistry::hasNonDefault() const { + ConfMap::Iter iter(fConfs); + SkTDArray *confArray; + while (iter.next(&confArray)) { + if (!confArray->getAt(0)->isDefault()) { + return true; + } + } + return false; +} + +void SkRTConfRegistry::printNonDefault(const char *fname) const { + SkWStream *o; + + if (NULL != fname) { + o = new SkFILEWStream(fname); + } else { + o = new SkDebugWStream(); + } + ConfMap::Iter iter(fConfs); + SkTDArray *confArray; + + while (iter.next(&confArray)) { + if (!confArray->getAt(0)->isDefault()) { + confArray->getAt(0)->print(o); + o->newline(); + } + } + + delete o; +} + +// register a configuration variable after its value has been set by the parser. +// we maintain a vector of these things instead of just a single one because the +// user might set the value after initialization time and we need to have +// all the pointers lying around, not just one. +void SkRTConfRegistry::registerConf(SkRTConfBase *conf) { + SkTDArray *confArray; + if (fConfs.find(conf->getName(), &confArray)) { + if (!conf->equals(confArray->getAt(0))) { + SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName()); + } else { + confArray->append(1, &conf); + } + } else { + confArray = new SkTDArray; + confArray->append(1, &conf); + fConfs.set(conf->getName(),confArray); + } +} + +template T doParse(const char *, bool *success ) { + SkDebugf("WARNING: Invoked non-specialized doParse function...\n"); + if (success) { + *success = false; + } + return (T) 0; +} + +template<> bool doParse(const char *s, bool *success) { + if (success) { + *success = true; + } + if (!strcmp(s,"1") || !strcmp(s,"true")) { + return true; + } + if (!strcmp(s,"0") || !strcmp(s,"false")) { + return false; + } + if (success) { + *success = false; + } + return false; +} + +template<> const char * doParse(const char * s, bool *success) { + if (success) { + *success = true; + } + return s; +} + +template<> int doParse(const char * s, bool *success) { + if (success) { + *success = true; + } + return atoi(s); +} + +template<> unsigned int doParse(const char * s, bool *success) { + if (success) { + *success = true; + } + return (unsigned int) atoi(s); +} + +template<> float doParse(const char * s, bool *success) { + if (success) { + *success = true; + } + return (float) atof(s); +} + +template<> double doParse(const char * s, bool *success) { + if (success) { + *success = true; + } + return atof(s); +} + +static inline void str_replace(char *s, char search, char replace) { + for (char *ptr = s ; *ptr ; ptr++) { + if (*ptr == search) { + *ptr = replace; + } + } +} + +template bool SkRTConfRegistry::parse(const char *name, T* value) { + const char *str = NULL; + + for (int i = fConfigFileKeys.count() - 1 ; i >= 0; i--) { + if (fConfigFileKeys[i]->equals(name)) { + str = fConfigFileValues[i]->c_str(); + break; + } + } + + SkString environment_variable("skia."); + environment_variable.append(name); + + const char *environment_value = getenv(environment_variable.c_str()); + if (environment_value) { + str = environment_value; + } else { + // apparently my shell doesn't let me have environment variables that + // have periods in them, so also let the user substitute underscores. + SkAutoTMalloc underscore_name(SkStrDup(environment_variable.c_str())); + str_replace(underscore_name.get(), '.', '_'); + environment_value = getenv(underscore_name.get()); + if (environment_value) { + str = environment_value; + } + } + + if (!str) { + return false; + } + + bool success; + T new_value = doParse(str, &success); + if (success) { + *value = new_value; + } else { + SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", + str, name); + } + return success; +} + +// need to explicitly instantiate the parsing function for every config type we might have... + +template bool SkRTConfRegistry::parse(const char *name, bool *value); +template bool SkRTConfRegistry::parse(const char *name, int *value); +template bool SkRTConfRegistry::parse(const char *name, unsigned int *value); +template bool SkRTConfRegistry::parse(const char *name, float *value); +template bool SkRTConfRegistry::parse(const char *name, double *value); +template bool SkRTConfRegistry::parse(const char *name, const char **value); + +template void SkRTConfRegistry::set(const char *name, + T value, + bool warnIfNotFound) { + SkTDArray *confArray; + if (!fConfs.find(name, &confArray)) { + if (warnIfNotFound) { + SkDebugf("WARNING: Attempting to set configuration value \"%s\"," + " but I've never heard of that.\n", name); + } + return; + } + SkASSERT(confArray != NULL); + for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) { + // static_cast here is okay because there's only one kind of child class. + SkRTConf *concrete = static_cast *>(*confBase); + + if (concrete) { + concrete->set(value); + } + } +} + +template void SkRTConfRegistry::set(const char *name, bool value, bool); +template void SkRTConfRegistry::set(const char *name, int value, bool); +template void SkRTConfRegistry::set(const char *name, unsigned int value, bool); +template void SkRTConfRegistry::set(const char *name, float value, bool); +template void SkRTConfRegistry::set(const char *name, double value, bool); +template void SkRTConfRegistry::set(const char *name, char * value, bool); + +SkRTConfRegistry &skRTConfRegistry() { + static SkRTConfRegistry r; + return r; +} + + +#ifdef SK_SUPPORT_UNITTEST + +#ifdef SK_BUILD_FOR_WIN32 +static void sk_setenv(const char* key, const char* value) { + _putenv_s(key, value); +} +#else +static void sk_setenv(const char* key, const char* value) { + setenv(key, value, 1); +} +#endif + +void SkRTConfRegistry::UnitTest() { + SkRTConfRegistry registryWithoutContents(true); + + sk_setenv("skia_nonexistent_item", "132"); + int result = 0; + registryWithoutContents.parse("nonexistent.item", &result); + SkASSERT(result == 132); +} + +SkRTConfRegistry::SkRTConfRegistry(bool) + : fConfs(100) { +} +#endif