configure.cc
来自「用于计算矩阵的特征值,及矩阵的其他运算.可以用与稀疏矩阵」· CC 代码 · 共 1,016 行 · 第 1/2 页
CC
1,016 行
// Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>// Copyright (C) 2002 Charless C. Fowlkes <fowlkes@eecs.berkeley.edu>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of the// License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.#include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>#include "configure.hh"#include "message.hh"#include "string.hh"#include "exception.hh"#include "util.hh"#include "types.hh"using Util::int64;using Util::String;using Util::Exception;using Util::Message; // So we can convert Type to strings. enum Type { BOOL, INT, FLOAT, STRING, ENUM }; static const char *typeNames[] = { "bool", "int", "float", "string", "enum" }; static const char *configKey = "config"; union Value { bool _bool; int64 _int; double _float; const char *_string; uint _enum; }; static void checkKey (const char *key); class Option { public: Option (Type type, const char *key, const char *description, const char *const *enumValues, Value value, bool printHex) { checkKey (key); _type = type; _key = strdup (key); _description = strdup (description); _enumValues = enumValues; _defaultValue = value; _value = value; _printHex = printHex; } bool equals (const char *key) { return (strcmp (key, _key) == 0); } Type _type; const char *_key; const char *_description; const char *const *_enumValues; Value _defaultValue; Value _value; bool _printHex; }; class Map { public: Map () { _count = 0; for (uint i = 0; i < _numBuckets; i++) { _buckets[i] = NULL; } } void put (Option * option) { if (get (option->_key) != NULL) { throw Exception (String ("Configure: Option %s is already registered.", option->_key)); } uint index = _hash (option->_key); _buckets[index] = new Node (option, _buckets[index]); _count++; } Option *get (const char *key) { uint index = _hash (key); for (Node * node = _buckets[index]; node != NULL; node = node->_next) { if (node->_option->equals (key)) { return node->_option; } } return NULL; } Option *getAlways (const char *key, Type type) { Option *option = get (key); if (option == NULL) { throw Exception (String ("Configure: Option %s is not registered.", key)); } if (option->_type != type) { throw Exception (String ("Configure:: Option %s " "is not type %s, it is type %s.", key, typeNames[type], typeNames[option->_type])); } return option; } Option **getAll () { Option **options = new Option *[_count]; uint c = 0; for (uint i = 0; i < _numBuckets; i++) { for (Node * node = _buckets[i]; node != NULL; node = node->_next) { options[c++] = node->_option; } } assert (c == _count); return options; } uint count () { return _count; } private: static const uint _numBuckets = 1024; class Node { public: Node (Option * option, Node * next) { _option = option; _next = next; } Option *_option; Node *_next; }; uint _hash (const char *key) { uint v = 0; for (const char *p = key; *p != '\0'; p++) { v = ((v << 1) + v) ^ (*p); } return v % _numBuckets; } Node *_buckets[_numBuckets]; uint _count; }; // Where the option->value map lives. static Map map; // Register options... void Configure::registerBool (const char *key, bool defaultValue, const char *description) { Value value; value._bool = defaultValue; Option *option = new Option (BOOL, key, description, NULL, value, false); map.put (option); } void Configure::registerInt (const char *key, int64 defaultValue, const char *description, bool printHex) { Value value; value._int = defaultValue; Option *option = new Option (INT, key, description, NULL, value, printHex); map.put (option); } void Configure::registerFloat (const char *key, double defaultValue, const char *description) { Value value; value._float = defaultValue; Option *option = new Option (FLOAT, key, description, NULL, value, false); map.put (option); } void Configure::registerString (const char *key, const char *defaultValue, const char *description) { Value value; value._string = (defaultValue == NULL) ? NULL : strdup (defaultValue); Option *option = new Option (STRING, key, description, NULL, value, false); map.put (option); } void Configure::registerEnum (const char *key, const char *const *values, uint defaultValue, const char *description) { Value value; value._enum = defaultValue; Option *option = new Option (ENUM, key, description, values, value, false); map.put (option); } // Retrieve options... bool Configure::getBool (const char *key) { Option *option = map.getAlways (key, BOOL); return option->_value._bool; } int64 Configure::getInt (const char *key) { Option *option = map.getAlways (key, INT); return option->_value._int; } double Configure::getFloat (const char *key) { Option *option = map.getAlways (key, FLOAT); return option->_value._float; } char * Configure::getString (const char *key) { Option *option = map.getAlways (key, STRING); if (option->_value._string == NULL) { return NULL; } else { return strdup (option->_value._string); } } uint Configure::getEnum (const char *key) { Option *option = map.getAlways (key, ENUM); return option->_value._enum; } // Check if the given string is valid as a key. static bool validKey (const char *key) { uint len = strlen (key); for (uint i = 0; i < len; i++) { int c = key[i]; if (c == '_') { continue; } if (c == ':') { continue; } if (i == 0 && isalpha (c)) { continue; } if (i > 0 && isalnum (c)) { continue; } return false; } return true; } // Make sure the given string is valid as a key. static void checkKey (const char *key) { if (key == NULL) { throw Exception ("Configure: NULL key."); } if (strcmp (key, configKey) == 0) { throw Exception (String ("Configure: Option conflicts with builtin" "config option '%s'.", configKey)); } if (!validKey (key)) { throw Exception (String ("Configure: Illegal key \"%s\".", key)); } } // Return true on success, false on failure. // <arg> := <key>=<value> static bool parseArg (const String & arg, String & key, String & value) { // Make sure there is an '=' character in the middle of arg. const char *p = arg.text (); const char *eq = strchr (p, '='); if (eq == NULL) { return false; } uint offset = eq - p; if (offset == 0) { return false; } key.clear (); value.clear (); uint i; for (i = 0; i < offset; i++) { key.append (p[i]); } assert (p[i] == '='); for (i++; i < arg.length (); i++) { value.append (p[i]); } return true; } // Throw exception on failure. static void parseBool (const char *s, bool & val) { String str ("%s", s); if (str == "no") { val = false; return; } if (str == "off") { val = false; return; } if (str == "0") { val = false; return; } if (str == "false") { val = false; return; } if (str == "yes") { val = true; return; } if (str == "on") { val = true; return; } if (str == "1") { val = true; return; } if (str == "true") { val = true; return; } throw Exception (String ("Error parsing boolean value \"%s\"", s)); } // Throw exception on failure. static void parseInt (const char *s, int64 & val) { int c, n; c = sscanf (s, "%lld%n", &val, &n); if (c == 1 && s[n] == '\0') { return; } c = sscanf (s, "%llx%n", &val, &n); if (c == 1 && s[n] == '\0') { return; } throw Exception (String ("Error parsing integer value \"%s\"", s)); } // Throw exception on failure. static void parseFloat (const char *s, double &val) { int n; int c = sscanf (s, "%lf%n", &val, &n); if (c == 1 && s[n] == '\0') { return; } throw Exception (String ("Error parsing floating-point value \"%s\"", s)); } // Throw exception on failure. static void parseEnum (const char *s, const char *const *values, uint & val) { String str ("%s", s); for (uint index = 0; values[index] != NULL; index++) { if (str == values[index]) { val = index; return; } } throw Exception (String ("Error parsing enumeration value \"%s\"", s)); } // Throw exception on failure. // Trailing whitespace is allowed. static Value parseValue (Type type, const char *const *enumValues, const char *s) { // Remove any whitespace from the end of s. uint len = strlen (s); while (len > 0 && isspace (s[len - 1])) { len--; } String val; val.append (len, s); Value value; switch (type) { case BOOL: parseBool (val, value._bool);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?