factor/native/string.c

241 lines
5.0 KiB
C
Raw Normal View History

2004-07-16 02:26:21 -04:00
#include "factor.h"
/* untagged */
2005-12-24 18:29:31 -05:00
F_STRING* allot_string(F_FIXNUM capacity)
2004-07-16 02:26:21 -04:00
{
2005-12-24 18:29:31 -05:00
F_STRING* string;
if(capacity < 0)
2006-02-07 19:09:46 -05:00
general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_integer(capacity),true);
2005-12-24 18:29:31 -05:00
string = allot_object(STRING_TYPE,
2005-02-09 19:58:53 -05:00
sizeof(F_STRING) + (capacity + 1) * CHARS);
/* strings are null-terminated in memory, even though they also
have a length field. The null termination allows us to add
the sizeof(F_STRING) to a Factor string to get a C-style
UTF16 string for C library calls. */
2005-03-21 20:59:30 -05:00
cput(SREF(string,capacity),(u16)'\0');
string->length = tag_fixnum(capacity);
2004-07-16 02:26:21 -04:00
return string;
}
/* call this after constructing a string */
void rehash_string(F_STRING* str)
2004-07-16 02:26:21 -04:00
{
s32 hash = 0;
2004-08-01 19:26:43 -04:00
CELL i;
CELL capacity = string_capacity(str);
for(i = 0; i < capacity; i++)
hash = (31*hash + string_nth(str,i));
str->hashcode = (s32)tag_fixnum(hash);
2004-07-16 02:26:21 -04:00
}
2005-05-18 16:26:22 -04:00
void primitive_rehash_string(void)
{
rehash_string(untag_string(dpop()));
}
2004-07-16 02:26:21 -04:00
/* untagged */
2005-12-24 18:29:31 -05:00
F_STRING *string(F_FIXNUM capacity, CELL fill)
2004-07-16 02:26:21 -04:00
{
2004-08-01 19:26:43 -04:00
CELL i;
2004-07-16 02:26:21 -04:00
F_STRING* string = allot_string(capacity);
2004-07-16 02:26:21 -04:00
for(i = 0; i < capacity; i++)
cput(SREF(string,i),fill);
2004-07-16 02:26:21 -04:00
2004-09-26 21:34:25 -04:00
rehash_string(string);
2004-07-16 02:26:21 -04:00
return string;
}
2005-12-24 18:29:31 -05:00
void primitive_string(void)
{
CELL initial = to_cell(dpop());
F_FIXNUM length = to_fixnum(dpop());
maybe_gc(string_size(length));
dpush(tag_object(string(length,initial)));
}
2005-06-10 16:08:00 -04:00
F_STRING* resize_string(F_STRING* string, F_FIXNUM capacity, u16 fill)
2004-07-16 02:26:21 -04:00
{
/* later on, do an optimization: if end of array is here, just grow */
2004-08-01 19:26:43 -04:00
CELL i;
2005-06-10 16:08:00 -04:00
CELL to_copy = string_capacity(string);
if(capacity < to_copy)
to_copy = capacity;
2004-07-16 02:26:21 -04:00
F_STRING* new_string = allot_string(capacity);
2004-07-16 02:26:21 -04:00
2005-06-10 16:08:00 -04:00
memcpy(new_string + 1,string + 1,to_copy * CHARS);
2004-07-16 02:26:21 -04:00
2005-06-10 16:08:00 -04:00
for(i = to_copy; i < capacity; i++)
cput(SREF(new_string,i),fill);
2004-07-16 02:26:21 -04:00
return new_string;
}
2005-06-10 16:08:00 -04:00
void primitive_resize_string(void)
2005-05-05 22:30:58 -04:00
{
F_STRING* string;
CELL capacity = to_fixnum(dpeek2());
maybe_gc(string_size(capacity));
2005-05-05 22:30:58 -04:00
string = untag_string_fast(dpop());
drepl(tag_object(resize_string(string,capacity,F)));
2005-05-05 22:30:58 -04:00
}
F_STRING *memory_to_string(const BYTE* string, CELL length)
2004-07-16 02:26:21 -04:00
{
F_STRING* s = allot_string(length);
2004-08-01 19:26:43 -04:00
CELL i;
2004-07-16 02:26:21 -04:00
for(i = 0; i < length; i++)
{
cput(SREF(s,i),*string);
string++;
2004-07-16 02:26:21 -04:00
}
2004-09-26 21:34:25 -04:00
rehash_string(s);
2004-07-16 02:26:21 -04:00
return s;
}
void primitive_memory_to_string(void)
{
CELL length = unbox_unsigned_cell();
BYTE *string = (BYTE*)unbox_unsigned_cell();
dpush(tag_object(memory_to_string(string,length)));
}
/* untagged */
F_STRING *from_c_string(const char *c_string)
{
2005-03-03 20:43:55 -05:00
return memory_to_string((BYTE*)c_string,strlen(c_string));
}
2004-09-19 17:39:28 -04:00
/* FFI calls this */
void box_c_string(const char *c_string)
2004-09-19 17:39:28 -04:00
{
dpush(c_string ? tag_object(from_c_string(c_string)) : F);
2004-09-19 17:39:28 -04:00
}
F_ARRAY *string_to_alien(F_STRING *s, bool check)
2004-07-16 02:26:21 -04:00
{
CELL capacity = string_capacity(s);
F_ARRAY *_c_str;
if(check)
{
CELL i;
for(i = 0; i < capacity; i++)
{
u16 ch = string_nth(s,i);
if(ch == '\0' || ch > 255)
2006-02-07 19:09:46 -05:00
general_error(ERROR_C_STRING,tag_object(s),true);
}
}
2004-07-16 02:26:21 -04:00
_c_str = allot_array(BYTE_ARRAY_TYPE,capacity / CELLS + 1);
BYTE *c_str = (BYTE*)(_c_str + 1);
string_to_memory(s,c_str);
c_str[capacity] = '\0';
return _c_str;
}
/* untagged */
char *to_c_string(F_STRING *s, bool check)
{
return (char*)(string_to_alien(s,check) + 1);
2004-11-13 18:07:18 -05:00
}
void string_to_memory(F_STRING *s, BYTE *string)
{
CELL i;
CELL capacity = string_capacity(s);
for(i = 0; i < capacity; i++)
string[i] = string_nth(s,i);
}
void primitive_string_to_memory(void)
{
BYTE *address = (BYTE*)unbox_unsigned_cell();
F_STRING *str = untag_string(dpop());
string_to_memory(str,address);
}
2004-09-19 17:39:28 -04:00
/* FFI calls this */
char *unbox_c_string(void)
2004-09-19 17:39:28 -04:00
{
CELL str = dpop();
2005-09-03 14:48:25 -04:00
if(type_of(str) == STRING_TYPE)
return to_c_string(untag_string(str),true);
2005-09-03 14:48:25 -04:00
else
return (char*)alien_offset(str);
2004-09-19 17:39:28 -04:00
}
/* this function is used when we really want only Factor strings as input, not
aliens. In particular, certian primitives crash if given a null pointer (f), so
we protect against this by using this function instead of unbox_c_string() */
char *pop_c_string(void)
{
return to_c_string(untag_string(dpop()),true);
}
/* FFI calls this */
u16 *unbox_utf16_string(void)
{
/* Return pointer to first character */
CELL obj = dpop();
if(type_of(obj) == STRING_TYPE)
{
F_STRING* str = untag_string(obj);
u16 *unboxed = (u16*)(str + 1);
CELL length = string_capacity(str);
CELL i;
for(i = 0; i < length; i++)
{
if(unboxed[i] == 0)
general_error(ERROR_C_STRING,obj,true);
}
return unboxed;
}
2005-09-03 17:59:53 -04:00
else
return (u16*)alien_offset(obj);
}
/* FFI calls this */
void box_utf16_string(u16 *unboxed)
{
CELL length = 0;
u16 *scan = unboxed;
F_STRING *str;
while(*scan++) length++;
str = allot_string(length);
memcpy((u16*)(str + 1),unboxed,length * sizeof(u16));
rehash_string(str);
dpush(tag_object(str));
}
2005-05-05 22:30:58 -04:00
void primitive_char_slot(void)
2004-07-16 02:26:21 -04:00
{
2005-05-05 22:30:58 -04:00
F_STRING* string = untag_string_fast(dpop());
CELL index = untag_fixnum_fast(dpop());
dpush(tag_fixnum(string_nth(string,index)));
2004-07-16 02:26:21 -04:00
}
2005-05-05 22:30:58 -04:00
void primitive_set_char_slot(void)
2004-07-16 02:26:21 -04:00
{
2005-05-05 22:30:58 -04:00
F_STRING* string = untag_string_fast(dpop());
CELL index = untag_fixnum_fast(dpop());
CELL value = untag_fixnum_fast(dpop());
set_string_nth(string,index,value);
}