mirror of
https://github.com/clockworkpi/Menu.git
synced 2025-12-13 16:08:55 +01:00
222 lines
6.6 KiB
Plaintext
Executable File
222 lines
6.6 KiB
Plaintext
Executable File
|
|
class cfg {
|
|
|
|
private import rt::c;
|
|
|
|
private alias
|
|
vector = std::vector,
|
|
string = std::string;
|
|
|
|
struct item {
|
|
name string;
|
|
value string;
|
|
cover char;
|
|
}
|
|
|
|
struct cfg {
|
|
items vector<item>;
|
|
filename string;
|
|
}
|
|
|
|
func constructor() {
|
|
constructor(this);
|
|
}
|
|
|
|
func destructor() {
|
|
destructor(this);
|
|
}
|
|
|
|
func open(filename. char) bool {
|
|
define {
|
|
SIZE_LIMIT = 0x1000000;
|
|
}
|
|
lambda read(filename. char, file_size& size_t) void [
|
|
var stream void = fopen(filename, "rb");
|
|
if stream == null;
|
|
return null;
|
|
defer fclose(stream);
|
|
if fseek(stream, 0, SEEK_END) < 0;
|
|
return null;
|
|
var tail long = ftell(stream);
|
|
if tail < 0 or tail > SIZE_LIMIT;
|
|
return null;
|
|
rewind(stream);
|
|
func = malloc(tail);
|
|
var offset size_t = 0;
|
|
var remain size_t = tail;
|
|
while remain {
|
|
var size size_t = fread(func + offset, 1, remain, stream);
|
|
if ferror(stream) {
|
|
free(func);
|
|
return null;
|
|
}
|
|
offset += size;
|
|
remain -= size;
|
|
}
|
|
file_size = offset;
|
|
];
|
|
var size size_t;
|
|
var buf. char = read(filename, size);
|
|
if buf == null;
|
|
return false;
|
|
defer free(buf);
|
|
this.items->clear();
|
|
this.filename->clear();
|
|
lambda skip_space(buf. char, index& size_t, size size_t) bool [
|
|
for ; index < size; index++ {
|
|
if !isspace(buf[index]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
];
|
|
lambda skip_line(buf. char, index& size_t, size size_t, end& size_t) bool [
|
|
for ; index < size; index++ {
|
|
var c char = buf[index];
|
|
if c == '\r' {
|
|
end = index;
|
|
if ++index < size {
|
|
if buf[index] == '\n' {
|
|
index++;
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
elseif c == '\n';
|
|
end = index++;
|
|
return true;
|
|
}
|
|
}
|
|
end = index;
|
|
return false;
|
|
];
|
|
lambda skip_name(buf. char, index& size_t, size size_t) bool [
|
|
for ; index < size; index++ {
|
|
var c char = buf[index];
|
|
if c == ' ' or c == '\t' or c == '\r' or c == '\n' or c == '=' {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
];
|
|
lambda skip_until(buf. char, index& size_t, size size_t, end char) bool [
|
|
for ; index < size; index++ {
|
|
if buf[index] == end {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
];
|
|
forvar index size_t = 0 ;; {
|
|
if !skip_space(buf, index, size);
|
|
break;
|
|
var name_offset size_t = index;
|
|
if !skip_name(buf, index, size);
|
|
break;
|
|
var name_size size_t = index - name_offset;
|
|
if !name_size;
|
|
return false;
|
|
if buf[index] ~= '=' {
|
|
if !skip_space(buf, ++index, size);
|
|
break;
|
|
if buf[index] ~= '=';
|
|
return false;
|
|
}
|
|
if !skip_space(buf, ++index, size);
|
|
break;
|
|
var value_offset size_t;
|
|
var value_size size_t;
|
|
var cover char;
|
|
if buf[index] == '\'' or
|
|
buf[index] == '\"' {
|
|
cover = buf[index];
|
|
value_offset = ++index;
|
|
if !skip_until(buf, index, size, cover);
|
|
break;
|
|
value_size = index++ - value_offset;
|
|
else
|
|
value_offset = index;
|
|
var end size_t;
|
|
skip_line(buf, index, size, end);
|
|
value_size = end - value_offset;
|
|
cover = 0;
|
|
}
|
|
var item. item = this.items->new();
|
|
item.name->set(buf + name_offset, name_size);
|
|
if value_size;
|
|
item.value->set(buf + value_offset, value_size);
|
|
item.cover = cover;
|
|
}
|
|
this.filename->set(filename);
|
|
return true;
|
|
}
|
|
|
|
func save(filename. char = null) bool {
|
|
var stream void;
|
|
if filename == null {
|
|
if this.filename->empty();
|
|
return false;
|
|
stream = fopen(this.filename->ptr(), "w");
|
|
else
|
|
stream = fopen(filename, "w");
|
|
}
|
|
if stream == null;
|
|
return false;
|
|
forvar index size_t = 0, count size_t = this.items->count(); index < count; index++ {
|
|
var item. item = this.items->at(index);
|
|
if item.cover {
|
|
fprintf("%s = %c%s%c\n",
|
|
item.name->ptr(),
|
|
item.cover,
|
|
item.value->ptr(),
|
|
item.cover);
|
|
else
|
|
fprintf("%s = %s\n",
|
|
item.name->ptr(),
|
|
item.value->ptr());
|
|
}
|
|
}
|
|
fclose(stream);
|
|
}
|
|
|
|
func find(name. char) .item {
|
|
var count size_t = this.items->count();
|
|
while count {
|
|
var item. item = this.items->at(--count);
|
|
if !strcasecmp(item.name->ptr(), name) {
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
func get(name. char) .char {
|
|
var item. item = this->find(name);
|
|
if item == null;
|
|
return null;
|
|
return item.value->ptr();
|
|
}
|
|
|
|
func set(name. char, value. char) bool {
|
|
var item. item = this->find(name);
|
|
if item == null;
|
|
return false;
|
|
item.value->set(value);
|
|
return true;
|
|
}
|
|
|
|
func add(name. char, value. char = null, cover char = '"') bool {
|
|
var item. item = this->find(name);
|
|
if item ~= null;
|
|
return false;
|
|
item = this.items->new();
|
|
item.name->set(name);
|
|
if value ~= null;
|
|
item.value->set(value);
|
|
item.cover = cover;
|
|
return true;
|
|
}
|
|
|
|
}
|