conf.cpp

来自「基于Linux下Epoll技术的EchoSvr」· C++ 代码 · 共 507 行

CPP
507
字号
/**
 * \file    conf.c
 * \author  Jason Armstrong <ja@riverdrums.com>
 * \version $Id: conf.c,v 1.3 2006/02/11 21:13:40 riverdrums Exp $
 *
 * \brief Configuration
 *
 * Functionality to read a configuration file that is in sections.
 * A section starts with a name within braces [name]
 *
 * All sections before this that don't fall within a [] section
 * are added to a section without a name ie ''
 *
 * Sections with the same name are amalgamated into one.
 * Name / value pairs within a section are not added unless they
 * are unique ie there is a check if they already exist.
 *
 * Multiple 'name' values are possible, and can be returned in
 * a NULL terminated array.
 */

/*
 COPYRIGHT (C) 2005 - 2006 RIVERDRUMS

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 "Conf.h"

/** Read buffer size increment */
#define RD_BUFSIZE  128

Config::Config(char* f)
{
	strcpy(filename,f);
	configer = NULL;
}

Config::~Config()
{
	cleanup();
		
}

void Config::cleanup()
{
  int i, j;
  struct rdconf *c = configer;
  if (c == NULL) {
    return;
  }

  /* Release in reverse order of acquisition */
  for (i = c->secti - 1; i >= 0; i--) {
    if (c->sect[i]) {
      if (c->sect[i]->name) free(c->sect[i]->name);

      for (j = c->sect[i]->nvi - 1; j >= 0; j--) {
        if (c->sect[i]->nv[j]) {
          if (c->sect[i]->nv[j]->name)  free(c->sect[i]->nv[j]->name);
          if (c->sect[i]->nv[j]->value) free(c->sect[i]->nv[j]->value);
          free(c->sect[i]->nv[j]);
        }
      }

      if (c->sect[i]->nv) free(c->sect[i]->nv);
      free(c->sect[i]);
    }
  }

  if (c) {
    if (c->sect) free(c->sect);
    free(c);
  }
  configer = NULL;
}
int Config::getInt(char *section, char *name)
{
  char *s = getValue(section, name);
  if (s == NULL) {
    return -1;   /* XXX This could also be a valid value */
  }
  return (atoi(s));
}



char *  Config::getValue(char *section, char *name)
{
	
  return getValue(configer,section,name);
}

char *  Config::getValue(struct rdconf *c,char *section, char *name)
{
	
  int i, j;
  if (c == NULL || section == NULL || name == NULL) {
    return NULL;
  }
  for (i = 0; i < c->secti; i++) {
    if (strcmp(c->sect[i]->name, section) == 0) {
      for (j = 0; j < c->sect[i]->nvi; j++) {
        if (strcmp(c->sect[i]->nv[j]->name, name) == 0) {
          return c->sect[i]->nv[j]->value;
        }
      }
    }
  }
  return NULL;
}

bool Config::read() 
{
	if(configer != NULL)
		return true;
		
	char *buf, *sect, *name, *val, *tmp, *p, *c;
  int linecount, len, gotsection, cs, s;
  int sectsize, namesize, valsize;
  struct rdconf *conf = NULL;
  FILE *fp = NULL;


  /* Initialise */
  linecount = len = cs = gotsection = s = 0;
  sectsize = namesize = valsize = 0;
  buf = sect = name = val = tmp = p = c = NULL;


  /* Allocate memory for our configuration structure */
  if ( (configer = (struct rdconf *) malloc(sizeof(struct rdconf))) == NULL) {
    false;
  }
	conf = configer;
  char* section = NULL;
  /* Start off with nothing */
  memset(conf, 0, sizeof(struct rdconf));


  /* Open the configuration file */
  if ( (fp = fopen(filename, "r")) == NULL) {
    //RD__error_add("Open '%s': %s", file, strerror(errno));
    cleanup();
    return false;
  }

  while ( (buf = readLine(fp, &buf, &s)) ) {

    linecount++;
    len = strlen(buf);

    /* How did that happen */
    if (len <= 0) {
      continue;
    }

    /* The last character MUST be a \n */
    if (buf[len - 1] != '\n') {
      continue;
    }


    /* Strip trailing spaces (include \r \n) from the end */
    while (len > 0 && isspace( (unsigned char) buf[len - 1])) {
      buf[--len] = 0;
    }

    /* Check for comments and empty lines */
    if (!buf[0] || buf[0] == '#' || buf[0] == ';') {
      continue;
    }

    p = buf;


    /* Get the section name */
    if (p[0] == '[') {

      /* 
       * If we're only looking for one section, and have it, then continue
       * reading, because we might have another section with the same name
       * later in the file. Disable adding name /values with gotsection
       */

      if (section && gotsection) {
        gotsection = 0;
        continue;
      }

      p++;

      if ( (c = strchr(p, ']')) == NULL) {
        //RD__error_add("Missing closing ] on line %d", linecount);
        fclose(fp); 
        if (buf) free(buf); if (sect) free(sect);
        if (name) free(name); if (val) free(val);
        cleanup();
        return false;
      }

      /* Read the section name up to the closing ] */
      if (sectsize < c - p) {
        if ( (tmp = (char *) realloc(sect, c - p + 1)) == NULL) {
          fclose(fp); 
          if (buf) free(buf); if (sect) free(sect);
          if (name) free(name); if (val) free(val);
          cleanup();
          return false;
        }
        sect     = tmp;
        sectsize = c - p;
      }
      memcpy(sect, p, c - p);
      sect[c - p] = 0;


      if (!section || (section && strcmp(sect, section) == 0)) {
        gotsection = 1;
      } else {
        continue;
      }


      if ( (cs = addSection(conf, sect)) < 0) {
        fclose(fp); 
        if (sect) free(sect); if (buf) free(buf);
        if (name) free(name); if (val) free(val);
        cleanup();
        return false;
      }

      continue;
    }


    /* 
     * Now we are in a section, reading name/value pairs
     */

    /*
     * Don't read here if we are looking for a particular section
     * and haven't found it yet.
     */
    if (section && !gotsection) {
      continue;
    }


    /* Remove leading spaces */
    while (*p && isspace( (unsigned char) *p)) {
      p++;
    }
    if (!*p || *p == '#' || *p == ';') {
      continue;
    }


    /* Read the name until the '=' delimiter */
    c = p;
    while (*c && *c != '=') {
      c++;
    }

    /* Don't abort on error, just carry on */
    if (!*c || *c != '=') {
      //fprintf(stderr, "Invalid line %d\n", linecount);
      continue;
    }

    if (namesize < c - p) {
      if ( (tmp = (char *) realloc(name, c - p + 1)) == NULL) {
        fclose(fp); 
        if (buf) free(buf); if (sect) free(sect);
        if (name) free(name); if (val) free(val);
        cleanup();
        return false;
      }
      name = tmp;
      namesize = c - p;
    }
    memcpy(name, p, c - p);
    name[c - p] = 0;


    /* Remove trailing spaces on the name */
    len = strlen(name);
    while (len && isspace( (unsigned char) name[len - 1]) ) {
      name[--len] = 0;
    }

    p = c + 1;

    /* Leading spaces in the value */
    while (*p && isspace( (unsigned char) *p)) {
      p++;
    }
    if (!*p) {
      continue;
    }

    c = p;

    while (*c) {
      c++;
    }

    if (valsize < c - p) {
      if ( (tmp = (char *) realloc(val, c - p + 1)) == NULL) {
        fclose(fp); 
        if (buf) free(buf); if (sect) free(sect);
        if (name) free(name); if (val) free(val);
        cleanup();
        return false;
      }
      val = tmp;
      valsize = c - p;
    }
    memcpy(val, p, c - p);
    val[c - p] = 0;

    len = strlen(val);
    while (len && isspace( (unsigned char) val[len - 1]) ) {
      val[--len] = 0;
    }

    /* If we're in the start of the file and haven't found a 
     * section yet, then add one without a name */
    if (!gotsection && !cs) {
      if ( (cs = addSection(conf, "")) < 0) {
        fclose(fp); 
        if (buf) free(buf); if (sect) free(sect);
        if (name) free(name); if (val) free(val);
        cleanup();
        return false;
      }

      gotsection = 1;
    }

    if (addNameval(conf, cs, name, val) < 0) {
      fclose(fp); 
      if (buf) free(buf); if (sect) free(sect);
      if (name) free(name); if (val) free(val);
      cleanup();
      return false;;
    }

  }

  if (buf)  free(buf);
  if (sect) free(sect);
  if (name) free(name);
  if (val)  free(val);

	fclose(fp);
	
  return true;
}

char * Config::readLine(FILE *f, char **buf, int *s)
{
  int o = 0;
  char *tmp;

  if (*buf == NULL) {
    if ( (*buf = (char *) malloc(RD_BUFSIZE)) == NULL) {
      return NULL;
    }
    *s = RD_BUFSIZE;
  }

  while (fgets(*buf + o, *s - o, f)) {
    if (strchr(*buf + o, '\n')) {
      return *buf;
    } else {
      o = *s - 1;
      *s += RD_BUFSIZE;
      if ( (tmp = (char *) realloc(*buf, *s)) == NULL) {
        return NULL;
      }
      *buf = tmp;
    }
  }
  return NULL;
}



int Config::addSection(struct rdconf *c,char *name)
{
  int i = 0;
  struct rdsection **tmp = c->sect;

  if ( (i = findSection(c, name)) >= 0) {
    return i;
  }

  i = c->secti;
  if ( (c->sect = 
          (struct rdsection **) 
          realloc(i ? c->sect : NULL,
                  (i + 1) * sizeof(struct rdsection *))) == NULL) {
    c->sect = tmp;
    return -1;
  }

  c->secti++;

  if ( (c->sect[i] = 
          (struct rdsection *) 
          malloc(sizeof(struct rdsection)) ) == NULL) {
    return -1;
  }

  memset(c->sect[i], 0, sizeof(struct rdsection));

  if ( (c->sect[i]->name = strdup(name)) == NULL) {
    return -1;
  }
  return c->secti - 1;
}


int Config::findSection(struct rdconf *c, char *name)
{
  int i;
  for (i = 0; i < c->secti; i++) 
  {
    if (strcmp(c->sect[i]->name, name) == 0) 
    	{
      return i;
    }
  }
  return -1;
}
int Config::addNameval(struct rdconf *c, int cs, char *name, char *val)
{
  struct rdnameval **tmp = NULL;
  int i = c->sect[cs]->nvi;
  char *check = NULL;

  if ( (check = getValue(c, c->sect[cs]->name, name)) &&
        strcmp(check, val) == 0) {
    /* It's there already */
    return 0;
  }

  /* Allocate a new rdnameval structure for storage */

  if ( (tmp = (struct rdnameval **) 
                realloc(c->sect[cs]->nv,
                        (i + 1) * sizeof(struct rdnameval *))) == NULL) {
    return -1;
  }

  c->sect[cs]->nv = tmp;
  c->sect[cs]->nvi++;

  if ( (c->sect[cs]->nv[i] = 
          (struct rdnameval *) 
          malloc(sizeof(struct rdnameval))) == NULL) {
    return -1;
  }

  memset(c->sect[cs]->nv[i], 0, sizeof(struct rdnameval));


  /* Duplicate the name */
  if ( (c->sect[cs]->nv[i]->name = strdup(name)) == NULL) {
    return -1;
  }

  /* Copy the  value (theoretically can be any length
   * but is limited to the size of the val buffer (256) above */

  if ( (c->sect[cs]->nv[i]->value = strdup(val)) == NULL) {
    return -1;
  }

  return 0;
}



/*int main(int argc, char *argv[]) 
{
	Config c("dgs.conf");
	if(c.read())
	{
		std::cout<<c.getInt("server","port");
	}	
}*/

⌨️ 快捷键说明

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