380 lines
8.2 KiB
C
380 lines
8.2 KiB
C
#include "tlang.h"
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <inttypes.h>
|
|
#include <errno.h>
|
|
void string_free(string_t* s)
|
|
{
|
|
free(s->text);
|
|
free(s);
|
|
}
|
|
string_t* string_create()
|
|
{
|
|
string_t* s2 = (string_t*)malloc(sizeof(string_t));
|
|
s2->capacity = 128;
|
|
s2->length = 0;
|
|
s2->text = (char*)malloc(sizeof(char)* s2->capacity);
|
|
|
|
return s2;
|
|
}
|
|
bool string_islong(string_t* s,int64_t* number)
|
|
{
|
|
//https://wiki.sei.cmu.edu/confluence/display/c/ERR34-C.+Detect+errors+when+converting+a+string+to+a+number
|
|
char* _s = string_dupp(s);
|
|
char *end;
|
|
int si;
|
|
bool res=false;
|
|
errno = 0;
|
|
|
|
*number = strtoll(_s, &end,0);
|
|
|
|
if (end == _s) {
|
|
res = false;
|
|
} else if ('\0' != *end) {
|
|
res=false;
|
|
} else if ( ERANGE == errno) {
|
|
res=false;
|
|
} else {
|
|
res = true;
|
|
|
|
|
|
/* Process si */
|
|
}
|
|
free(_s);
|
|
return res;
|
|
}
|
|
|
|
bool string_isnumber(string_t* s,double* number)
|
|
{
|
|
//https://wiki.sei.cmu.edu/confluence/display/c/ERR34-C.+Detect+errors+when+converting+a+string+to+a+number
|
|
char* _s = string_dupp(s);
|
|
char *end;
|
|
int si;
|
|
bool res=false;
|
|
errno = 0;
|
|
|
|
*number = strtod(_s, &end);
|
|
|
|
if (end == _s) {
|
|
res = false;
|
|
} else if ('\0' != *end) {
|
|
res=false;
|
|
} else if ( ERANGE == errno) {
|
|
res=false;
|
|
} else {
|
|
res = true;
|
|
|
|
|
|
/* Process si */
|
|
}
|
|
free(_s);
|
|
return res;
|
|
}
|
|
void string_ensure(string_t* a)
|
|
{
|
|
if(a->length + 1 > a->capacity)
|
|
{
|
|
a->capacity = a->length + 128;
|
|
a->text=(char*)realloc(a->text,a->capacity);
|
|
|
|
}
|
|
}
|
|
|
|
void string_appendp(string_t* a,const char* str)
|
|
{
|
|
size_t len = strlen(str);
|
|
int _len = a->length;
|
|
a->length = _len+ (int)len;
|
|
string_ensure(a);
|
|
memcpy(a->text+_len,str,len);
|
|
}
|
|
void string_appendc(string_t* a,char c)
|
|
{
|
|
char str[2];
|
|
str[0] = c;
|
|
str[1] = 0;
|
|
string_appendp(a,str);
|
|
}
|
|
|
|
void string_appendn(string_t* s,double val)
|
|
{
|
|
char txt[1000];
|
|
//snprintf(txt,len,"%f",val);
|
|
int64_t bigNo = (int64_t)val;
|
|
val -= bigNo;
|
|
uint64_t littleNo = (uint64_t)(val * 100000000000.0);
|
|
while(littleNo % 10 == 0 && littleNo != 0)
|
|
{
|
|
littleNo /= 10;
|
|
}
|
|
snprintf(txt,1000,"%" PRId64 "", bigNo);
|
|
string_appendp(s,txt);
|
|
|
|
if(littleNo > 0)
|
|
{
|
|
snprintf(txt,1000,".%" PRIu64 "", littleNo);
|
|
string_appendp(s,txt);
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
void string_clear(string_t* s)
|
|
{
|
|
s->length=0;
|
|
}
|
|
char* string_dupp(string_t* s)
|
|
{
|
|
char* text = (char*)malloc(sizeof(char) * (s->length + 1));
|
|
memcpy(text,s->text,s->length);
|
|
text[s->length] = 0;
|
|
return text;
|
|
}
|
|
string_t* string_dups(string_t* s)
|
|
{
|
|
string_t* s2 = (string_t*)malloc(sizeof(string_t));
|
|
s2->capacity = s->length + 128;
|
|
s2->length = s->length;
|
|
s2->text = (char*)malloc(sizeof(char)* s2->capacity);
|
|
memcpy(s2->text,s->text,s->length);
|
|
return s2;
|
|
}
|
|
void string_appends(string_t* a,string_t* b)
|
|
{
|
|
|
|
int _len = a->length;
|
|
a->length = _len+ b->length;
|
|
string_ensure(a);
|
|
memcpy(a->text+_len,b->text,b->length);
|
|
}
|
|
const char* string_trimstart(const char* ptr,char c)
|
|
{
|
|
while(*ptr != '\0')
|
|
{
|
|
if(*ptr != c) break;
|
|
ptr++;
|
|
}
|
|
return ptr;
|
|
}
|
|
string_t* string_substring(string_t* s,int start,int length)
|
|
{
|
|
if(s->length - start < length)
|
|
{
|
|
length = s->length - start;
|
|
}
|
|
if(length < 0) length = 0;
|
|
string_t* dest = string_create();
|
|
if(length == 0) return dest;
|
|
dest->length = length;
|
|
string_ensure(dest);
|
|
memcpy(dest->text,s->text + start,length);
|
|
return dest;
|
|
}
|
|
string_t* string_remove(string_t* s,int start,int length)
|
|
{
|
|
string_t* dest = string_create();
|
|
int after = start + length;
|
|
if(start > 0)
|
|
{
|
|
string_t* dest1=string_substring(s,0,start);
|
|
string_appends(dest,dest1);
|
|
string_free(dest1);
|
|
}
|
|
|
|
if(after < s->length - 1)
|
|
{
|
|
string_t* dest1=string_substring(s,after,s->length-after);
|
|
string_appends(dest,dest1);
|
|
string_free(dest1);
|
|
}
|
|
return dest;
|
|
}
|
|
string_t* string_trimstarts(string_t* s,char c)
|
|
{
|
|
int i = 0;
|
|
while(i<s->length)
|
|
{
|
|
if(s->text[i] != c) break;
|
|
i++;
|
|
}
|
|
string_t* s2=string_create();
|
|
int _len = s->length-i;
|
|
s2->length = _len;
|
|
string_ensure(s2);
|
|
memcpy(s2->text,s->text+i,_len);
|
|
return s2;
|
|
}
|
|
|
|
int string_lastindexof(string_t* s,char c)
|
|
{
|
|
int i;
|
|
for(i=s->length-1;i>=0;i--)
|
|
{
|
|
if(s->text[i] == c) return i;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int string_indexof(string_t* s,char c)
|
|
{
|
|
int i=0;
|
|
for(i=0;i<s->length;i++)
|
|
{
|
|
if(s->text[i] == c) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
string_t* string_trimends(string_t* s,char c)
|
|
{
|
|
int i = s->length-1;
|
|
while(i>=0)
|
|
{
|
|
if(s->text[i] != c) break;
|
|
i--;
|
|
}
|
|
i++;
|
|
if(i < 0) i=0;
|
|
string_t* s2=string_create();
|
|
s2->length =i;
|
|
string_ensure(s2);
|
|
memcpy(s2->text,s->text,s2->length);
|
|
return s2;
|
|
}
|
|
void string_read(string_t* str,void* ptr,size_t(*_cb)(void*,size_t,size_t,void*))
|
|
{
|
|
char buffer[1024];
|
|
size_t read=0;
|
|
do{
|
|
read = _cb(buffer,1,1024,ptr);
|
|
if(read > 0){
|
|
int _len = str->length;
|
|
str->length = _len+ (int)read;
|
|
string_ensure(str);
|
|
memcpy(str->text+_len,buffer,read);
|
|
}
|
|
}while(read > 0);
|
|
}
|
|
bool string_samep(string_t* s,const char* text)
|
|
{
|
|
size_t len = strlen(text);
|
|
if(s->length != len)
|
|
{
|
|
return false;
|
|
}
|
|
return memcmp(s->text,text,len) == 0;
|
|
}
|
|
bool string_sames(string_t* s,string_t* b)
|
|
{
|
|
int len = b->length;
|
|
if(s->length != b->length)
|
|
{
|
|
return false;
|
|
}
|
|
return memcmp(s->text,b->text,(size_t)len) == 0;
|
|
}
|
|
bool string_is_del(string_t* text,int i,string_t* del)
|
|
{
|
|
if(text->length - i < del->length) return false;
|
|
int j;
|
|
for(j = 0;j<del->length;j++)
|
|
{
|
|
if(text->text[j+i] != del->text[j]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
tobject_t* string_split(runtime_t* rt,string_t* text,string_t* del,int max,bool empty)
|
|
{
|
|
if(max == 0)
|
|
{
|
|
max = 2147483647;
|
|
}
|
|
int j = 0;
|
|
int i;
|
|
tobject_t* o = tobject_create_array(rt,0);
|
|
string_t* b=string_create();
|
|
for(i=0;i<text->length;i++)
|
|
{
|
|
if(string_is_del(text,i,del) && j < max - 1)
|
|
{
|
|
i += del->length;
|
|
j++;
|
|
if(b->length > 0 || empty)
|
|
list_add(&o->data.list,tobject_string(rt,string_dups(b)));
|
|
string_clear(b);
|
|
}
|
|
if(i<text->length)
|
|
string_appendc(b,text->text[i]);
|
|
}
|
|
if(b->length > 0 || empty)
|
|
list_add(&o->data.list,tobject_string(rt,string_dups(b)));
|
|
|
|
string_free(b);
|
|
return o;
|
|
/* List<string> p = new List<string>();
|
|
StringBuilder b= new StringBuilder();
|
|
for(int i = 0;i<text.Length;i++)
|
|
{
|
|
if(IsDelimiter(text,i,delimiter) && j < c - 1)
|
|
{
|
|
i += delimiter.Length;
|
|
j++;
|
|
if(b.Length > 0 || empty)
|
|
p.Add(b.ToString());
|
|
|
|
b.Clear();
|
|
}
|
|
|
|
b.Append(text[i]);
|
|
|
|
}
|
|
if(b.Length > 0 || empty)
|
|
p.Add(b.ToString());
|
|
return p.ToArray();
|
|
*/
|
|
}
|
|
bool string_startswith(string_t* haystack,string_t* needle)
|
|
{
|
|
int len = needle->length;
|
|
if(haystack->length < len) return false;
|
|
int i;
|
|
for(i = 0;i < len;i++)
|
|
{
|
|
if(needle->text[i] != haystack->text[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
bool string_endswith(string_t* haystack,string_t* needle)
|
|
{
|
|
int len = needle->length;
|
|
if(haystack->length < len) return false;
|
|
int i;
|
|
for(i = 0;i < needle->length;i++)
|
|
{
|
|
if(needle->text[i] != haystack->text[haystack->length-needle->length+i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
string_t* string_replace(string_t* text,string_t* old,string_t* new)
|
|
{
|
|
int j = 0;
|
|
int i;
|
|
|
|
string_t* b=string_create();
|
|
for(i=0;i<text->length;i++)
|
|
{
|
|
if(string_is_del(text,i,old))
|
|
{
|
|
i += old->length;
|
|
j++;
|
|
string_appends(b,new);
|
|
|
|
}
|
|
if(i<text->length)
|
|
string_appendc(b,text->text[i]);
|
|
}
|
|
|
|
|
|
return b;
|
|
}
|