File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / configfile.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:04:28 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v002, v001, HEAD
nono 0.0.1

//
// nono
// Copyright (C) 2018 [email protected]
//

#include "configfile.h"
#include <sys/stat.h>

Config *gConfig;

// コンストラクタ
Config::Config(const std::string& dir)
{
	assert(!dir.empty());
	dirname = dir;
	if (dirname.back() != '/') {
		dirname.push_back('/');
	}

	filename = dirname + "config.ini";
}

// デストラクタ
Config::~Config()
{
}

// 設定ファイルをロードする。
// 成功すれば true を返す。
bool
Config::Load()
{
	char buf[1024];
	FILE *fp;
	int line;
	bool rv = false;

	fp = fopen(filename.c_str(), "r");
	if (fp == NULL) {
		warn("config file cannot open: %s", filename.c_str());
		return false;
	}

	for (line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) {
		const char *key = buf;
		char *val;

		// chomp
		buf[strcspn(buf, "\r\n")] = '\0';

		// 空行は無視
		if (buf[0] == '\0') {
			continue;
		}

		// '=' の前後で key, val に分ける
		val = strchr(buf, '=');
		if (val == NULL) {
			warnx("%s: %d: syntax error", filename.c_str(), line);
			goto abort;
		}

		*val++ = '\0';

		map[key] = val;
	}

	rv = true;
 abort:
	fclose(fp);
	return rv;
}

// 変数 key の値を int として読み出します。
// 変数がなければ defaultvalue を返します。
// 変数があって整数として解釈できない場合は 0 になります。
int
Config::ReadInt(const char *key, int defaultvalue)
{
	if (map.count(key)) {
		const std::string& str = map[key];
		return atoi(str.c_str());
	} else {
		return defaultvalue;
	}
}

// 変数 key の値を文字列として読み出します。
// 変数がなければ defaultvalue を返します。
std::string
Config::ReadStr(const char *key, const std::string& defaultvalue)
{
	if (map.count(key)) {
		return map[key];
	} else {
		return defaultvalue;
	}
}

// 関連するファイルのパスを取得。
std::string
Config::SearchFile(const char *name_c) const
{
	std::string name = name_c;
	std::string path;
	struct stat st;

	// ファイルがあるかどうかを調べるだけで、存在したけどそれに何らか
	// 不都合があったら次を試すとかはしない。

	// 1. 設定ファイルディレクトリ
	path = GetConfigDir() + name;
	if (stat(path.c_str(), &st) == 0) {
		return path;
	}

	// 2. 共通ディレクトリ(?)
	// XXX 共通ディレクトリを返す関数を用意したほうがいいか
	path = GetConfigDir() + "../" + name;
	if (stat(path.c_str(), &st) == 0) {
		return path;
	}

	return "";
}

// エラー表示を共通化したい
void
Config::Err(const std::string& key, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	Errv(key.c_str(), fmt, ap);
	va_end(ap);
}

// エラー表示を共通化したい
void
Config::Err(const char *key, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	Errv(key, fmt, ap);
	va_end(ap);
}

// エラー表示本体
void
Config::Errv(const char *key, const char *fmt, va_list ap)
{
	char fmtbuf[1024];

	vsnprintf(fmtbuf, sizeof(fmtbuf), fmt, ap);
	warnx("%s: \"%s\": %s", GetFilename().c_str(), key, fmtbuf);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.