ngx_c_conf.h:
#ifndef __NGX_CONF_H__
#define __NGX_CONF_H__
#include <vector>
#include "ngx_global.h" // 一些全局/通用定义
// 类名遵照一定的命名规范,比如这里第一个字母是C,后续的单词首字母大写
class CConfig
{
// 单例设计模式
private:
CConfig();
public:
~CConfig();
private:
static CConfig* m_instance;
public:
static CConfig* GetInstance()
{
if (m_instance == NULL)
{
// 锁
if (m_instance == NULL)
{
m_instance = new CConfig();
static CGarhuishou cl;
}
// 放锁
}
return m_instance;
}
class CGarhuishou // 类中套类,用于释放对象
{
public:
~CGarhuishou()
{
if (CConfig::m_instance)
{
delete CConfig::m_instance;
CConfig::m_instance = NULL;
}
}
};
public:
bool Load(const char* pconfName); // 装载配置文件
const char* GetString(const char* p_itemname);
int GetIntDefault(const char* p_itemname, const int def);
public:
std::vector<LPCConfItem> m_ConfigItemList; // 存储配置信息的列表
};
#endif
ngx_c_conf.cxx:
// 系统头文件放上边
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
// 自定义头文件放下边,因为g++中用了-I参数,所以这里用<>也可以
#include "ngx_func.h" // 函数声明
#include "ngx_c_conf.h" // 和配置文件处理相关的类,名字带c_表示和类有关
// 静态成员赋值
CConfig* CConfig::m_instance = NULL;
// 构造函数
CConfig::CConfig()
{
}
// 析构函数
CConfig::~CConfig()
{
std::vector<LPCConfItem>::iterator pos;
for (pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
{
delete (*pos);
}
m_ConfigItemList.clear();
}
// 装载配置文件
bool CConfig::Load(const char* pconfName)
{
FILE *fp;
fp = fopen(pconfName, "r");
if (fp == NULL) return false;
// 每一行配置文件读出来都放这里,每行配置都不要太长,保持500字符以内,防止出现问题
char linebuf[501];
// 走到这里,文件打开成功
while (!feof(fp)) // 检查文件是否结束,没有结束则条件成立
{
// 注意写法的严密性,商业代码就是要首先确保代码的严密性
// 从文件中读数据,每次读一行,一行最多不要超过500个字符
if (fgets(linebuf, 500, fp) == NULL) continue; // 读取失败直接continue
if (linebuf[0] == 0) continue; // 读到空行直接continue
// 处理注释行
if (*linebuf == ';' || *linebuf == ' ' || *linebuf == '#' || *linebuf == '\t' || *linebuf == '\n') continue;
lblprocstring:
// 屁股后边若有换行、回车、空格等都截取掉
if (strlen(linebuf) > 0)
{
if (linebuf[strlen(linebuf) - 1] == 10 || linebuf[strlen(linebuf) - 1] == 13 || linebuf[strlen(linebuf) - 1] == 32)
{
linebuf[strlen(linebuf) - 1] = 0;
goto lblprocstring;
}
}
if (linebuf[0] == 0) continue; // 空行直接continue
if (*linebuf == '[') continue; // [开头的也不处理
// 这种配置项"ListenPort = 5678"走下来
char* ptmp = strchr(linebuf, '=');
if (ptmp != NULL)
{
LPCConfItem p_confitem = new CConfItem; // 注意前边类型带LP,后边new这里的类型不带
memset(p_confitem, 0, sizeof(CConfItem));
strncpy(p_confitem->ItemName, linebuf, (int)(ptmp - linebuf)); // 等号左侧的拷贝到p_confitem->ItemName
strcpy(p_confitem->ItemContent, ptmp + 1); // 等号右侧的拷贝到p_confitem->ItemContent
Rtrim(p_confitem->ItemName);
Ltrim(p_confitem->ItemName);
Rtrim(p_confitem->ItemContent);
Ltrim(p_confitem->ItemContent);
// printf("itemname=%s | itemcontent=%s\n", p_confitem->ItemName, p_confitem->ItemContent);
m_ConfigItemList.push_back(p_confitem); // 内存要释放,因为这里是new出来的
}
}
fclose(fp); // 这步不可忘记
return true;
}
// 根据ItemName获取配置信息字符串,不修改不用互斥
const char* CConfig::GetString(const char* p_itemname)
{
std::vector<LPCConfItem>::iterator pos;
for (pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
{
if (strcasecmp((*pos)->ItemName, p_itemname) == 0)
{
return (*pos)->ItemContent;
}
}
return NULL;
}
// 根据ItemName获取数字类型配置信息,不修改不用互斥
int CConfig::GetIntDefault(const char* p_itemname, const int def)
{
std::vector<LPCConfItem>::iterator pos;
for (pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
{
if (strcasecmp((*pos)->ItemName, p_itemname) == 0)
{
return atoi((*pos)->ItemContent);
}
}
return def;
}