mirror of
https://github.com/clockworkpi/Menu.git
synced 2025-12-14 00:18:53 +01:00
209 lines
5.4 KiB
Plaintext
Executable File
209 lines
5.4 KiB
Plaintext
Executable File
|
|
class std+, strings {
|
|
|
|
private import rt::c;
|
|
|
|
struct strings {
|
|
mem dmem;
|
|
offsets vector<uint32>;
|
|
index size_t;
|
|
}
|
|
|
|
func constructor() {
|
|
constructor(this);
|
|
this.mem.page = 0x2000;
|
|
this.index = -1;
|
|
}
|
|
|
|
func destructor() {
|
|
destructor(this);
|
|
}
|
|
|
|
func clear(free_mem bool = false) {
|
|
if free_mem {
|
|
this.mem->free();
|
|
else
|
|
this.mem.used = 0;
|
|
}
|
|
this.offsets->clear(free_mem);
|
|
this.index = -1;
|
|
}
|
|
|
|
func add(str. char, len size_t = 0) .char {
|
|
var used size_t = this.mem.used;
|
|
this.offsets->push_back(used);
|
|
if !len;
|
|
len = strlen(str);
|
|
if len;
|
|
this.mem->write(str, len);
|
|
.this.mem->alloc_t<char>() = 0;
|
|
return this.mem.ptr + used;
|
|
}
|
|
|
|
func load_file(file_name. char, trim bool = true, ignore_blank bool = true) int {
|
|
var stream void = fopen(file_name, "rb");
|
|
if stream == null;
|
|
return -1;
|
|
defer fclose(stream);
|
|
if fgetc(stream) ~= 0xef or
|
|
fgetc(stream) ~= 0xbb or
|
|
fgetc(stream) ~= 0xbf {
|
|
if fseek(stream, 0, SEEK_SET) < 0;
|
|
return -1;
|
|
}
|
|
var count size_t = this.offsets->count();
|
|
var buf(0x2000) char;
|
|
for ;; {
|
|
if fgets(&buf, 0x2000, stream) == null;
|
|
break;
|
|
var line. char = &buf;
|
|
var len size_t = strlen(line);
|
|
if len and line[len - 1] == 10 {
|
|
if len > 1 and line[len - 2] == 13 {
|
|
len -= 2;
|
|
else
|
|
len -= 1;
|
|
}
|
|
line[len] = 0;
|
|
}
|
|
if trim {
|
|
while isspace(.line);
|
|
line += 1, len--;
|
|
while len {
|
|
if !isspace(line[len - 1]);
|
|
break;
|
|
len--;
|
|
}
|
|
}
|
|
if !len and ignore_blank;
|
|
continue;
|
|
this->add(line, len);
|
|
}
|
|
return this.offsets->count() - count;
|
|
}
|
|
|
|
func split(str. char, del. char) uint {
|
|
func = 1;
|
|
var len size_t = strlen(del);
|
|
var tmp. char;
|
|
while (tmp = strstr(str, del)) ~= null;
|
|
this->add(str, tmp - str), str = tmp + len, func++;
|
|
this->add(str);
|
|
}
|
|
|
|
inline count() size_t {
|
|
return this.offsets->count();
|
|
}
|
|
|
|
inline empty() bool {
|
|
return this.offsets->count() == 0;
|
|
}
|
|
|
|
inline item(index size_t) .char {
|
|
return this.mem.ptr + .this.offsets->at(index);
|
|
}
|
|
|
|
func next_item(loop bool = false) .char {
|
|
var count size_t = this->count();
|
|
if !count;
|
|
return null;
|
|
var index size_t = this.index;
|
|
if index < count {
|
|
func = this->item(index), this.index++;
|
|
else
|
|
this.index = 0;
|
|
if index == -1 or loop {
|
|
func = this->next_item();
|
|
else
|
|
func = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
func prev_item() .char {
|
|
var index size_t = this.index;
|
|
if index == -1;
|
|
return null;
|
|
var count size_t = this->count();
|
|
if !count;
|
|
return null;
|
|
if index and index < count {
|
|
return this->item(index - 1);
|
|
else
|
|
return this->item(count - 1);
|
|
}
|
|
}
|
|
|
|
func rollback() {
|
|
var count size_t = this->count();
|
|
if count {
|
|
if this.index ~= -1 {
|
|
if this.index and this.index < count {
|
|
this.index--;
|
|
else
|
|
this.index = count - 1;
|
|
}
|
|
}
|
|
else
|
|
this.index = -1;
|
|
}
|
|
}
|
|
|
|
func first_item() .char {
|
|
if !this->count();
|
|
return null;
|
|
return this->item(0);
|
|
}
|
|
|
|
func last_item() .char {
|
|
var count size_t = this->count();
|
|
if !count;
|
|
return null;
|
|
return this->item(count - 1);
|
|
}
|
|
|
|
func rnd_item() .char {
|
|
var count size_t = this->count();
|
|
if !count;
|
|
return null;
|
|
return this->item(random<size_t>(count));
|
|
}
|
|
|
|
func join(str. string, del. char = null) .char {
|
|
forvar index size_t = 0, count size_t = this->count(); index < count; index++ {
|
|
str->append(this->item(index));
|
|
if del ~= null;
|
|
str->append(del);
|
|
}
|
|
return str->ptr();
|
|
}
|
|
|
|
func exists(str. char, index. size_t = null) bool {
|
|
forvar i size_t = 0, c size_t = this->count(); i < c; i++ {
|
|
if !strcmp(this->item(i), str) {
|
|
if index ~= null;
|
|
.index = i;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
func existsi(str. char, index. size_t = null) bool {
|
|
forvar i size_t = 0, c size_t = this->count(); i < c; i++ {
|
|
if !strcasecmp(this->item(i), str) {
|
|
if index ~= null;
|
|
.index = i;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// fixme
|
|
inline remove(index size_t) bool {
|
|
return this.offsets->erase(index);
|
|
}
|
|
|
|
}
|