Extended bytes, bytesiterator; added bytearray
This commit is contained in:
parent
f1928b2526
commit
b4887a78b0
@ -207,8 +207,8 @@ static inline KrkValue discardStringBuilder(struct StringBuilder * sb) {
|
||||
#define IS_dictkeys(o) krk_isInstanceOf(o,vm.baseClasses->dictkeysClass)
|
||||
#define AS_dictkeys(o) ((struct DictKeys*)AS_OBJECT(o))
|
||||
|
||||
#define IS_bytesiterator(o) (krk_isInstanceOf(o,vm.baseClasses->bytesiteratorClass))
|
||||
#define AS_bytesiterator(o) (AS_INSTANCE(o))
|
||||
#define IS_bytearray(o) (krk_isInstanceOf(o,vm.baseClasses->bytearrayClass))
|
||||
#define AS_bytearray(o) ((struct ByteArray*)AS_INSTANCE(o))
|
||||
|
||||
#ifndef unpackError
|
||||
#define unpackError(fromInput) return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(fromInput));
|
||||
|
@ -166,6 +166,7 @@ struct BaseClasses {
|
||||
KrkClass * codeobjectClass; /**< Static compiled bytecode container (KrkCodeObject) */
|
||||
KrkClass * generatorClass; /**< Generator object. */
|
||||
KrkClass * notImplClass; /**< NotImplementedType */
|
||||
KrkClass * bytearrayClass; /**< Mutable array of bytes */
|
||||
};
|
||||
|
||||
/**
|
||||
|
212
src/obj_bytes.c
212
src/obj_bytes.c
@ -4,6 +4,11 @@
|
||||
#include <kuroko/memory.h>
|
||||
#include <kuroko/util.h>
|
||||
|
||||
struct ByteArray {
|
||||
KrkInstance inst;
|
||||
KrkValue actual;
|
||||
};
|
||||
|
||||
#define AS_bytes(o) AS_BYTES(o)
|
||||
#define CURRENT_CTYPE KrkBytes *
|
||||
#define CURRENT_NAME self
|
||||
@ -39,6 +44,10 @@ KRK_METHOD(bytes,__init__,{
|
||||
out->bytes[i] = AS_INTEGER(AS_LIST(argv[1])->values[i]);
|
||||
}
|
||||
return krk_pop();
|
||||
} else if (IS_bytearray(argv[1])) {
|
||||
return OBJECT_VAL(krk_newBytes(
|
||||
AS_BYTES(AS_bytearray(argv[1])->actual)->length,
|
||||
AS_BYTES(AS_bytearray(argv[1])->actual)->bytes));
|
||||
}
|
||||
|
||||
return krk_runtimeError(vm.exceptions->typeError, "Can not convert '%s' to bytes", krk_typeName(argv[1]));
|
||||
@ -177,6 +186,25 @@ KRK_METHOD(bytes,__add__,{
|
||||
return finishStringBuilderBytes(&sb);
|
||||
})
|
||||
|
||||
#define BYTES_WRAP_SOFT(val) \
|
||||
if (val < 0) val += self->length; \
|
||||
if (val < 0) val = 0; \
|
||||
if (val > (krk_integer_type)self->length) val = self->length
|
||||
|
||||
KRK_METHOD(bytes,__getslice__,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
if (!(IS_INTEGER(argv[1]) || IS_NONE(argv[1]))) return TYPE_ERROR(int or None, argv[1]);
|
||||
if (!(IS_INTEGER(argv[2]) || IS_NONE(argv[2]))) return TYPE_ERROR(int or None, argv[2]);
|
||||
krk_integer_type start = IS_NONE(argv[1]) ? 0 : AS_INTEGER(argv[1]);
|
||||
krk_integer_type end = IS_NONE(argv[2]) ? (krk_integer_type)self->length : AS_INTEGER(argv[2]);
|
||||
BYTES_WRAP_SOFT(start);
|
||||
BYTES_WRAP_SOFT(end);
|
||||
if (end < start) end = start;
|
||||
krk_integer_type len = end - start;
|
||||
|
||||
return OBJECT_VAL(krk_newBytes(len, &self->bytes[start]));
|
||||
})
|
||||
|
||||
FUNC_SIG(bytesiterator,__init__);
|
||||
|
||||
KRK_METHOD(bytes,__iter__,{
|
||||
@ -191,40 +219,155 @@ KRK_METHOD(bytes,__iter__,{
|
||||
})
|
||||
|
||||
#undef CURRENT_CTYPE
|
||||
#define CURRENT_CTYPE KrkInstance *
|
||||
|
||||
struct BytesIterator {
|
||||
KrkInstance inst;
|
||||
KrkValue l;
|
||||
size_t i;
|
||||
};
|
||||
|
||||
#define CURRENT_CTYPE struct BytesIterator *
|
||||
#define IS_bytesiterator(o) krk_isInstanceOf(o,vm.baseClasses->bytesiteratorClass)
|
||||
#define AS_bytesiterator(o) (struct BytesIterator*)AS_OBJECT(o)
|
||||
|
||||
static void _bytesiterator_gcscan(KrkInstance * self) {
|
||||
krk_markValue(((struct BytesIterator*)self)->l);
|
||||
}
|
||||
|
||||
KRK_METHOD(bytesiterator,__init__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
CHECK_ARG(1,bytes,KrkBytes*,base);
|
||||
krk_push(OBJECT_VAL(self));
|
||||
krk_attachNamedObject(&self->fields, "s", (KrkObj*)base);
|
||||
krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(0));
|
||||
return krk_pop();
|
||||
CHECK_ARG(1,bytes,KrkBytes*,bytes);
|
||||
self->l = argv[1];
|
||||
self->i = 0;
|
||||
return argv[0];
|
||||
})
|
||||
|
||||
KRK_METHOD(bytesiterator,__call__,{
|
||||
METHOD_TAKES_NONE();
|
||||
KrkValue _bytes;
|
||||
KrkValue _counter;
|
||||
const char * errorStr = NULL;
|
||||
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("s")), &_bytes)) {
|
||||
errorStr = "no str pointer";
|
||||
goto _corrupt;
|
||||
}
|
||||
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("i")), &_counter)) {
|
||||
errorStr = "no index";
|
||||
goto _corrupt;
|
||||
}
|
||||
|
||||
if ((size_t)AS_INTEGER(_counter) >= AS_BYTES(_bytes)->length) {
|
||||
KrkValue _list = self->l;
|
||||
size_t _counter = self->i;
|
||||
if (_counter >= AS_BYTES(_list)->length) {
|
||||
return argv[0];
|
||||
} else {
|
||||
krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(AS_INTEGER(_counter)+1));
|
||||
return INTEGER_VAL(AS_BYTES(_bytes)->bytes[AS_INTEGER(_counter)]);
|
||||
self->i = _counter + 1;
|
||||
return INTEGER_VAL(AS_BYTES(_list)->bytes[_counter]);
|
||||
}
|
||||
_corrupt:
|
||||
return krk_runtimeError(vm.exceptions->typeError, "Corrupt bytes iterator: %s", errorStr);
|
||||
})
|
||||
|
||||
#undef CURRENT_CTYPE
|
||||
#define CURRENT_CTYPE struct ByteArray *
|
||||
|
||||
static void _bytearray_gcscan(KrkInstance * self) {
|
||||
krk_markValue(((struct ByteArray*)self)->actual);
|
||||
}
|
||||
|
||||
KRK_METHOD(bytearray,__init__,{
|
||||
METHOD_TAKES_AT_MOST(1);
|
||||
if (argc < 2) {
|
||||
self->actual = OBJECT_VAL(krk_newBytes(0,NULL));
|
||||
} else if (IS_BYTES(argv[1])) {
|
||||
self->actual = OBJECT_VAL(krk_newBytes(AS_BYTES(argv[1])->length, AS_BYTES(argv[1])->bytes));
|
||||
} else if (IS_INTEGER(argv[1])) {
|
||||
self->actual = OBJECT_VAL(krk_newBytes(AS_INTEGER(argv[1]),NULL));
|
||||
} else {
|
||||
return krk_runtimeError(vm.exceptions->valueError, "expected bytes");
|
||||
}
|
||||
return argv[0];
|
||||
})
|
||||
|
||||
/* bytes objects are not interned; need to do this the old-fashioned way. */
|
||||
KRK_METHOD(bytearray,__eq__,{
|
||||
if (!IS_bytearray(argv[1])) return BOOLEAN_VAL(0);
|
||||
struct ByteArray * them = AS_bytearray(argv[1]);
|
||||
return BOOLEAN_VAL(krk_valuesEqual(self->actual, them->actual));
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,__repr__,{
|
||||
METHOD_TAKES_NONE();
|
||||
struct StringBuilder sb = {0};
|
||||
pushStringBuilderStr(&sb, "bytearray(", 10);
|
||||
|
||||
krk_push(self->actual);
|
||||
KrkValue repred_bytes = krk_callDirect(vm.baseClasses->bytesClass->_reprer, 1);
|
||||
pushStringBuilderStr(&sb, AS_STRING(repred_bytes)->chars, AS_STRING(repred_bytes)->length);
|
||||
pushStringBuilder(&sb,')');
|
||||
return finishStringBuilder(&sb);
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,__getitem__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
CHECK_ARG(1,int,krk_integer_type,asInt);
|
||||
|
||||
if (asInt < 0) asInt += (long)AS_BYTES(self->actual)->length;
|
||||
if (asInt < 0 || asInt >= (long)AS_BYTES(self->actual)->length) {
|
||||
return krk_runtimeError(vm.exceptions->indexError, "bytearray index out of range: %d", (int)asInt);
|
||||
}
|
||||
|
||||
return INTEGER_VAL(AS_BYTES(self->actual)->bytes[asInt]);
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,__setitem__,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
CHECK_ARG(1,int,krk_integer_type,asInt);
|
||||
CHECK_ARG(2,int,krk_integer_type,val);
|
||||
|
||||
if (asInt < 0) asInt += (long)AS_BYTES(self->actual)->length;
|
||||
if (asInt < 0 || asInt >= (long)AS_BYTES(self->actual)->length) {
|
||||
return krk_runtimeError(vm.exceptions->indexError, "bytearray index out of range: %d", (int)asInt);
|
||||
}
|
||||
AS_BYTES(self->actual)->bytes[asInt] = val;
|
||||
|
||||
return INTEGER_VAL(AS_BYTES(self->actual)->bytes[asInt]);
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,__len__,{
|
||||
return INTEGER_VAL(AS_BYTES(self->actual)->length);
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,__contains__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
CHECK_ARG(1,int,krk_integer_type,val);
|
||||
for (size_t i = 0; i < AS_BYTES(self->actual)->length; ++i) {
|
||||
if (AS_BYTES(self->actual)->bytes[i] == val) return BOOLEAN_VAL(1);
|
||||
}
|
||||
return BOOLEAN_VAL(0);
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,decode,{
|
||||
METHOD_TAKES_NONE();
|
||||
return OBJECT_VAL(krk_copyString((char*)AS_BYTES(self->actual)->bytes, AS_BYTES(self->actual)->length));
|
||||
})
|
||||
|
||||
#define BYTEARRAY_WRAP_SOFT(val) \
|
||||
if (val < 0) val += AS_BYTES(self->actual)->length; \
|
||||
if (val < 0) val = 0; \
|
||||
if (val > (krk_integer_type)AS_BYTES(self->actual)->length) val = AS_BYTES(self->actual)->length
|
||||
|
||||
KRK_METHOD(bytearray,__getslice__,{
|
||||
METHOD_TAKES_EXACTLY(2);
|
||||
if (!(IS_INTEGER(argv[1]) || IS_NONE(argv[1]))) return TYPE_ERROR(int or None, argv[1]);
|
||||
if (!(IS_INTEGER(argv[2]) || IS_NONE(argv[2]))) return TYPE_ERROR(int or None, argv[2]);
|
||||
krk_integer_type start = IS_NONE(argv[1]) ? 0 : AS_INTEGER(argv[1]);
|
||||
krk_integer_type end = IS_NONE(argv[2]) ? (krk_integer_type)AS_BYTES(self->actual)->length : AS_INTEGER(argv[2]);
|
||||
BYTEARRAY_WRAP_SOFT(start);
|
||||
BYTEARRAY_WRAP_SOFT(end);
|
||||
if (end < start) end = start;
|
||||
krk_integer_type len = end - start;
|
||||
|
||||
return OBJECT_VAL(krk_newBytes(len, &AS_BYTES(self->actual)->bytes[start]));
|
||||
})
|
||||
|
||||
KRK_METHOD(bytearray,__iter__,{
|
||||
METHOD_TAKES_NONE();
|
||||
KrkInstance * output = krk_newInstance(vm.baseClasses->bytesiteratorClass);
|
||||
|
||||
krk_push(OBJECT_VAL(output));
|
||||
FUNC_NAME(bytesiterator,__init__)(2, (KrkValue[]){krk_peek(0), self->actual},0);
|
||||
krk_pop();
|
||||
|
||||
return OBJECT_VAL(output);
|
||||
})
|
||||
|
||||
|
||||
_noexport
|
||||
void _createAndBind_bytesClass(void) {
|
||||
KrkClass * bytes = ADD_BASE_CLASS(vm.baseClasses->bytesClass, "bytes", vm.baseClasses->objectClass);
|
||||
@ -237,6 +380,7 @@ void _createAndBind_bytesClass(void) {
|
||||
BIND_METHOD(bytes,__len__);
|
||||
BIND_METHOD(bytes,__contains__);
|
||||
BIND_METHOD(bytes,__getitem__);
|
||||
BIND_METHOD(bytes,__getslice__);
|
||||
BIND_METHOD(bytes,__eq__);
|
||||
BIND_METHOD(bytes,__add__);
|
||||
BIND_METHOD(bytes,__iter__);
|
||||
@ -247,7 +391,27 @@ void _createAndBind_bytesClass(void) {
|
||||
krk_finalizeClass(bytes);
|
||||
|
||||
KrkClass * bytesiterator = ADD_BASE_CLASS(vm.baseClasses->bytesiteratorClass, "bytesiterator", vm.baseClasses->objectClass);
|
||||
bytesiterator->allocSize = sizeof(struct BytesIterator);
|
||||
bytesiterator->_ongcscan = _bytesiterator_gcscan;
|
||||
BIND_METHOD(bytesiterator,__init__);
|
||||
BIND_METHOD(bytesiterator,__call__);
|
||||
krk_finalizeClass(bytesiterator);
|
||||
|
||||
KrkClass * bytearray = ADD_BASE_CLASS(vm.baseClasses->bytearrayClass, "bytearray", vm.baseClasses->objectClass);
|
||||
bytearray->allocSize = sizeof(struct ByteArray);
|
||||
bytearray->_ongcscan = _bytearray_gcscan;
|
||||
KRK_DOC(BIND_METHOD(bytearray,__init__),
|
||||
"@brief A mutable array of bytes.\n"
|
||||
"@arguments bytes=None");
|
||||
BIND_METHOD(bytearray,__repr__);
|
||||
BIND_METHOD(bytearray,__len__);
|
||||
BIND_METHOD(bytearray,__contains__);
|
||||
BIND_METHOD(bytearray,__getitem__);
|
||||
BIND_METHOD(bytearray,__setitem__);
|
||||
BIND_METHOD(bytearray,__getslice__);
|
||||
BIND_METHOD(bytearray,__eq__);
|
||||
BIND_METHOD(bytearray,__iter__);
|
||||
BIND_METHOD(bytearray,decode);
|
||||
krk_defineNative(&bytearray->methods,"__str__",FUNC_NAME(bytearray,__repr__)); /* alias */
|
||||
krk_finalizeClass(bytearray);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user