Menu/60_Utils/02_Bean/beans/std/strings.bean
2019-07-02 03:32:09 +00:00

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);
}
}