⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initconfigfileparser.cpp

📁 mysql-5.0.22.tar.gz源码包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2003 MySQL AB   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 */#include <ndb_global.h>#include "InitConfigFileParser.hpp"#include "Config.hpp"#include "MgmtErrorReporter.hpp"#include <NdbOut.hpp>#include "ConfigInfo.hpp"#include <m_string.h>const int MAX_LINE_LENGTH = 1024;  // Max length of line of text in config filestatic void trim(char *);static void require(bool v) { if(!v) abort();}//****************************************************************************//  Ctor / Dtor//****************************************************************************InitConfigFileParser::InitConfigFileParser(FILE * out){  m_info = new ConfigInfo();  m_errstream = out ? out : stdout;}InitConfigFileParser::~InitConfigFileParser() {  delete m_info;}//****************************************************************************//  Read Config File//****************************************************************************InitConfigFileParser::Context::Context(const ConfigInfo * info, FILE * out)  :  m_userProperties(true), m_configValues(1000, 20) {  m_config = new Properties(true);  m_defaults = new Properties(true);  m_errstream = out;}InitConfigFileParser::Context::~Context(){  if(m_config != 0)    delete m_config;  if(m_defaults != 0)    delete m_defaults;}Config *InitConfigFileParser::parseConfig(const char * filename) {  FILE * file = fopen(filename, "r");  if(file == 0){    fprintf(m_errstream, "Error opening file: %s\n", filename);    return 0;  }    Config * ret = parseConfig(file);  fclose(file);  return ret;}Config *InitConfigFileParser::parseConfig(FILE * file) {  char line[MAX_LINE_LENGTH];  Context ctx(m_info, m_errstream);   ctx.m_lineno = 0;  ctx.m_currentSection = 0;  /*************   * Open file *   *************/  if (file == NULL) {    return 0;  }  /***********************   * While lines to read *   ***********************/  while (fgets(line, MAX_LINE_LENGTH, file)) {    ctx.m_lineno++;    trim(line);    if (isEmptyLine(line)) // Skip if line is empty or comment      continue;       // End with NULL instead of newline    if (line[strlen(line)-1] == '\n')      line[strlen(line)-1] = '\0';        /********************************     * 1. Parse new default section *     ********************************/    if (char* section = parseDefaultSectionHeader(line)) {      if(!storeSection(ctx)){	free(section);	ctx.reportError("Could not store previous default section "			"of configuration file.");	return 0;      }      BaseString::snprintf(ctx.fname, sizeof(ctx.fname), section); free(section);      ctx.type             = InitConfigFileParser::DefaultSection;      ctx.m_sectionLineno  = ctx.m_lineno;      ctx.m_currentSection = new Properties(true);      ctx.m_userDefaults   = NULL;      require((ctx.m_currentInfo = m_info->getInfo(ctx.fname)) != 0);      require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname)) != 0);      continue;    }        /************************     * 2. Parse new section *     ************************/    if (char* section = parseSectionHeader(line)) {      if(!storeSection(ctx)){	free(section);	ctx.reportError("Could not store previous section "			"of configuration file.");	return 0;      }      BaseString::snprintf(ctx.fname, sizeof(ctx.fname), section);      free(section);      ctx.type             = InitConfigFileParser::Section;      ctx.m_sectionLineno  = ctx.m_lineno;            ctx.m_currentSection = new Properties(true);      ctx.m_userDefaults   = getSection(ctx.fname, ctx.m_defaults);      require((ctx.m_currentInfo    = m_info->getInfo(ctx.fname)) != 0);      require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname)) != 0);      continue;    }        /****************************     * 3. Parse name-value pair *     ****************************/    if (!parseNameValuePair(ctx, line)) {      ctx.reportError("Could not parse name-value pair in config file.");      return 0;    }  }    if (ferror(file)){    ctx.reportError("Failure in reading");    return 0;  }   if(!storeSection(ctx)) {    ctx.reportError("Could not store section of configuration file.");    return 0;  }  return run_config_rules(ctx);}Config*InitConfigFileParser::run_config_rules(Context& ctx){  for(size_t i = 0; ConfigInfo::m_ConfigRules[i].m_configRule != 0; i++){    ctx.type             = InitConfigFileParser::Undefined;    ctx.m_currentSection = 0;    ctx.m_userDefaults   = 0;    ctx.m_currentInfo    = 0;    ctx.m_systemDefaults = 0;        Vector<ConfigInfo::ConfigRuleSection> tmp;    if(!(* ConfigInfo::m_ConfigRules[i].m_configRule)(tmp, ctx,						      ConfigInfo::m_ConfigRules[i].m_ruleData))      return 0;    for(size_t j = 0; j<tmp.size(); j++){      BaseString::snprintf(ctx.fname, sizeof(ctx.fname), tmp[j].m_sectionType.c_str());      ctx.type             = InitConfigFileParser::Section;      ctx.m_currentSection = tmp[j].m_sectionData;      ctx.m_userDefaults   = getSection(ctx.fname, ctx.m_defaults);      require((ctx.m_currentInfo    = m_info->getInfo(ctx.fname)) != 0);      require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname)) != 0);      if(!storeSection(ctx))	return 0;    }  }  Uint32 nConnections = 0;  Uint32 nComputers = 0;  Uint32 nNodes = 0;  Uint32 nExtConnections = 0;  const char * system = "?";  ctx.m_userProperties.get("NoOfConnections", &nConnections);  ctx.m_userProperties.get("NoOfComputers", &nComputers);  ctx.m_userProperties.get("NoOfNodes", &nNodes);  ctx.m_userProperties.get("ExtNoOfConnections", &nExtConnections);  ctx.m_userProperties.get("ExtSystem", &system);  ctx.m_config->put("NoOfConnections", nConnections);  ctx.m_config->put("NoOfComputers", nComputers);  ctx.m_config->put("NoOfNodes", nNodes);  char tmpLine[MAX_LINE_LENGTH];  BaseString::snprintf(tmpLine, MAX_LINE_LENGTH, "EXTERNAL SYSTEM_");  strncat(tmpLine, system, MAX_LINE_LENGTH);  strncat(tmpLine, ":NoOfConnections", MAX_LINE_LENGTH);  ctx.m_config->put(tmpLine, nExtConnections);    Config * ret = new Config();  ret->m_configValues = (struct ndb_mgm_configuration*)ctx.m_configValues.getConfigValues();  ret->m_oldConfig = ctx.m_config; ctx.m_config = 0;  return ret;}//****************************************************************************//  Parse Name-Value Pair//****************************************************************************bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line){  if (ctx.m_currentSection == NULL){    ctx.reportError("Value specified outside section");    return false;  }  // *************************************  //  Split string at first occurrence of   //  '=' or ':'  // *************************************  Vector<BaseString> tmp_string_split;  if (BaseString(line).split(tmp_string_split,			     "=:", 2) != 2)  {    ctx.reportError("Parse error");    return false;  }  // *************************************  //  Remove all after #  // *************************************  Vector<BaseString> tmp_string_split2;  tmp_string_split[1].split(tmp_string_split2,			    "#", 2);  tmp_string_split[1]=tmp_string_split2[0];  // *************************************  // Remove leading and trailing chars  // *************************************  {    for (int i = 0; i < 2; i++)      tmp_string_split[i].trim("\r\n \t");   }  // *************************************  // First in split is fname  // *************************************  const char *fname= tmp_string_split[0].c_str();  if (!ctx.m_currentInfo->contains(fname)) {    ctx.reportError("[%s] Unknown parameter: %s", ctx.fname, fname);    return false;  }  ConfigInfo::Status status = m_info->getStatus(ctx.m_currentInfo, fname);  if (status == ConfigInfo::CI_NOTIMPLEMENTED) {    ctx.reportWarning("[%s] %s not yet implemented", ctx.fname, fname);  }  if (status == ConfigInfo::CI_DEPRICATED) {    const char * desc = m_info->getDescription(ctx.m_currentInfo, fname);    if(desc && desc[0]){      ctx.reportWarning("[%s] %s is depricated, use %s instead", 			ctx.fname, fname, desc);    } else if (desc == 0){      ctx.reportWarning("[%s] %s is depricated", ctx.fname, fname);    }   }  // ***********************  //  Store name-value pair  // ***********************  return storeNameValuePair(ctx, fname, tmp_string_split[1].c_str());}//****************************************************************************//  STORE NAME-VALUE pair in properties section //****************************************************************************bool InitConfigFileParser::storeNameValuePair(Context& ctx,					 const char* fname, 					 const char* value) {    const char * pname = fname;  if (ctx.m_currentSection->contains(pname)) {    ctx.reportError("[%s] Parameter %s specified twice", ctx.fname, fname);    return false;  }    // ***********************  //  Store name-value pair  // ***********************  const ConfigInfo::Type type = m_info->getType(ctx.m_currentInfo, fname);  switch(type){  case ConfigInfo::CI_BOOL: {    bool value_bool;    if (!convertStringToBool(value, value_bool)) {      ctx.reportError("Illegal boolean value for parameter %s", fname);      return false;    }    MGM_REQUIRE(ctx.m_currentSection->put(pname, value_bool));    break;  }  case ConfigInfo::CI_INT:  case ConfigInfo::CI_INT64:{    Uint64 value_int;    if (!convertStringToUint64(value, value_int)) {      ctx.reportError("Illegal integer value for parameter %s", fname);      return false;    }    if (!m_info->verify(ctx.m_currentInfo, fname, value_int)) {      ctx.reportError("Illegal value %s for parameter %s.\n"		      "Legal values are between %Lu and %Lu", value, fname,		      m_info->getMin(ctx.m_currentInfo, fname), 		      m_info->getMax(ctx.m_currentInfo, fname));      return false;    }    if(type == ConfigInfo::CI_INT){      MGM_REQUIRE(ctx.m_currentSection->put(pname, (Uint32)value_int));    } else {      MGM_REQUIRE(ctx.m_currentSection->put64(pname, value_int));    }    break;  }  case ConfigInfo::CI_STRING:    MGM_REQUIRE(ctx.m_currentSection->put(pname, value));    break;  case ConfigInfo::CI_SECTION:    abort();  }  return true;}//****************************************************************************//  Is Empty Line//****************************************************************************bool InitConfigFileParser::isEmptyLine(const char* line) const {  int i;    // Check if it is a comment line  if (line[0] == '#') return true;                 // Check if it is a line with only spaces  for (i = 0; i < MAX_LINE_LENGTH && line[i] != '\n' && line[i] != '\0'; i++) {    if (line[i] != ' ' && line[i] != '\t') return false;  }  return true;}//****************************************************************************//  Convert String to Int//****************************************************************************bool InitConfigFileParser::convertStringToUint64(const char* s, 						 Uint64& val,						 Uint32 log10base) {  if (s == NULL)    return false;  if (strlen(s) == 0)     return false;  errno = 0;  char* p;  Int64 v = strtoll(s, &p, log10base);  if (errno != 0)    return false;    long mul = 0;  if (p != &s[strlen(s)]){    char * tmp = strdup(p);    trim(tmp);    switch(tmp[0]){    case 'k':    case 'K':      mul = 10;      break;    case 'M':      mul = 20;      break;    case 'G':      mul = 30;      break;    default:      free(tmp);      return false;    }    free(tmp);  }    val = (v << mul);  return true;}bool InitConfigFileParser::convertStringToBool(const char* s, bool& val) {  if (s == NULL) return false;  if (strlen(s) == 0) return false;  if (!strcmp(s, "Y") || !strcmp(s, "y") ||       !strcmp(s, "Yes") || !strcmp(s, "YES") || !strcmp(s, "yes") ||       !strcmp(s, "True") || !strcmp(s, "TRUE") || !strcmp(s, "true") ||      !strcmp(s, "1")) {    val = true;    return true;  }  if (!strcmp(s, "N") || !strcmp(s, "n") ||       !strcmp(s, "No") || !strcmp(s, "NO") || !strcmp(s, "no") ||       !strcmp(s, "False") || !strcmp(s, "FALSE") || !strcmp(s, "false") ||      !strcmp(s, "0")) {    val = false;    return true;  }    return false;  // Failure to convert}//****************************************************************************//  Parse Section Header//****************************************************************************static voidtrim(char * str){  int len = strlen(str);  for(len--;      (str[len] == '\r' || str[len] == '\n' ||        str[len] == ' ' || str[len] == '\t') && 	len > 0;       len--)    str[len] = 0;    int pos = 0;  while(str[pos] == ' ' || str[pos] == '\t')    pos++;    if(str[pos] == '\"' && str[len] == '\"') {    pos++;    str[len] = 0;    len--;  }    memmove(str, &str[pos], len - pos + 2);}char* InitConfigFileParser::parseSectionHeader(const char* line) const {  char * tmp = strdup(line);  if(tmp[0] != '['){    free(tmp);    return NULL;  }  if(tmp[strlen(tmp)-1] != ']'){    free(tmp);    return NULL;  }  tmp[strlen(tmp)-1] = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -