mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
reimpl bytes
This commit is contained in:
parent
fb5e57b98b
commit
724f693761
@ -48,43 +48,74 @@ struct StarWrapper{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Bytes{
|
struct Bytes{
|
||||||
std::vector<char> _v;
|
unsigned char* _data;
|
||||||
bool valid;
|
int _size;
|
||||||
|
|
||||||
int size() const noexcept { return (int)_v.size(); }
|
int size() const noexcept { return _size; }
|
||||||
int operator[](int i) const noexcept { return (int)(uint8_t)_v[i]; }
|
int operator[](int i) const noexcept { return (int)_data[i]; }
|
||||||
const char* data() const noexcept { return _v.data(); }
|
const unsigned char* data() const noexcept { return _data; }
|
||||||
|
|
||||||
bool operator==(const Bytes& rhs) const{ return _v == rhs._v && valid == rhs.valid; }
|
bool operator==(const Bytes& rhs) const{
|
||||||
bool operator!=(const Bytes& rhs) const{ return _v != rhs._v || valid != rhs.valid; }
|
if(_size != rhs._size) return false;
|
||||||
|
for(int i=0; i<_size; i++) if(_data[i] != rhs._data[i]) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool operator!=(const Bytes& rhs) const{ return !(*this == rhs); }
|
||||||
|
|
||||||
Str str() const noexcept { return Str(_v.data(), _v.size()); }
|
Str str() const noexcept { return Str((char*)_data, _size); }
|
||||||
std::string_view sv() const noexcept { return std::string_view(_v.data(), _v.size()); }
|
std::string_view sv() const noexcept { return std::string_view((char*)_data, _size); }
|
||||||
|
|
||||||
Bytes() : valid(false) {}
|
Bytes() : _data(nullptr), _size(0) {}
|
||||||
Bytes(std::vector<char>&& v): _v(std::move(v)), valid(true) {}
|
Bytes(unsigned char* p, int size): _data(p), _size(size) {}
|
||||||
Bytes(std::string_view sv): valid(true) {
|
Bytes(const std::vector<unsigned char>& v){
|
||||||
_v.resize(sv.size());
|
_data = new unsigned char[v.size()];
|
||||||
for(int i=0; i<sv.size(); i++) _v[i] = sv[i];
|
_size = v.size();
|
||||||
|
for(int i=0; i<_size; i++) _data[i] = v[i];
|
||||||
|
}
|
||||||
|
Bytes(std::string_view sv){
|
||||||
|
_data = new unsigned char[sv.size()];
|
||||||
|
_size = sv.size();
|
||||||
|
for(int i=0; i<_size; i++) _data[i] = sv[i];
|
||||||
}
|
}
|
||||||
Bytes(const Str& str): Bytes(str.sv()) {}
|
Bytes(const Str& str): Bytes(str.sv()) {}
|
||||||
operator bool() const noexcept { return valid; }
|
operator bool() const noexcept { return _data != nullptr; }
|
||||||
|
|
||||||
// copy constructor
|
// copy constructor
|
||||||
Bytes(const Bytes& rhs) : _v(rhs._v), valid(rhs.valid) {}
|
Bytes(const Bytes& rhs){
|
||||||
|
_data = new unsigned char[rhs._size];
|
||||||
|
_size = rhs._size;
|
||||||
|
for(int i=0; i<_size; i++) _data[i] = rhs._data[i];
|
||||||
|
}
|
||||||
|
|
||||||
// move constructor
|
// move constructor
|
||||||
Bytes(Bytes&& rhs) noexcept : _v(std::move(rhs._v)), valid(rhs.valid) {
|
Bytes(Bytes&& rhs) noexcept {
|
||||||
rhs.valid = false;
|
_data = rhs._data;
|
||||||
|
_size = rhs._size;
|
||||||
|
rhs._data = nullptr;
|
||||||
|
rhs._size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bytes& operator=(Bytes&& rhs) noexcept {
|
Bytes& operator=(Bytes&& rhs) noexcept {
|
||||||
_v = std::move(rhs._v);
|
delete[] _data;
|
||||||
valid = rhs.valid;
|
_data = rhs._data;
|
||||||
rhs.valid = false;
|
_size = rhs._size;
|
||||||
|
rhs._data = nullptr;
|
||||||
|
rhs._size = 0;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<unsigned char*, int> detach() noexcept {
|
||||||
|
unsigned char* p = _data;
|
||||||
|
int size = _size;
|
||||||
|
_data = nullptr;
|
||||||
|
_size = 0;
|
||||||
|
return {p, size};
|
||||||
|
}
|
||||||
|
|
||||||
|
~Bytes(){
|
||||||
|
delete[] _data;
|
||||||
|
}
|
||||||
|
|
||||||
// delete copy assignment
|
// delete copy assignment
|
||||||
Bytes& operator=(const Bytes& rhs) = delete;
|
Bytes& operator=(const Bytes& rhs) = delete;
|
||||||
};
|
};
|
||||||
|
@ -171,19 +171,17 @@ void add_module_base64(VM* vm){
|
|||||||
// b64encode
|
// b64encode
|
||||||
vm->bind_func<1>(mod, "b64encode", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "b64encode", [](VM* vm, ArgsView args){
|
||||||
Bytes& b = CAST(Bytes&, args[0]);
|
Bytes& b = CAST(Bytes&, args[0]);
|
||||||
std::vector<char> out(b.size() * 2);
|
unsigned char* p = new unsigned char[b.size() * 2];
|
||||||
int size = base64_encode((const unsigned char*)b.data(), b.size(), out.data());
|
int size = base64_encode((const unsigned char*)b.data(), b.size(), (char*)p);
|
||||||
out.resize(size);
|
return VAR(Bytes(p, size));
|
||||||
return VAR(Bytes(std::move(out)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// b64decode
|
// b64decode
|
||||||
vm->bind_func<1>(mod, "b64decode", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "b64decode", [](VM* vm, ArgsView args){
|
||||||
Bytes& b = CAST(Bytes&, args[0]);
|
Bytes& b = CAST(Bytes&, args[0]);
|
||||||
std::vector<char> out(b.size());
|
unsigned char* p = new unsigned char[b.size()];
|
||||||
int size = base64_decode(b.data(), b.size(), (unsigned char*)out.data());
|
int size = base64_decode((const char*)b.data(), b.size(), p);
|
||||||
out.resize(size);
|
return VAR(Bytes(p, size));
|
||||||
return VAR(Bytes(std::move(out)));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +248,9 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(BUILD_BYTES) {
|
TARGET(BUILD_BYTES) {
|
||||||
const Str& s = CAST(Str&, TOP());
|
const Str& s = CAST(Str&, TOP());
|
||||||
std::vector<char> buffer(s.size);
|
unsigned char* p = new unsigned char[s.size];
|
||||||
memcpy(buffer.data(), s.data, s.size);
|
memcpy(p, s.data, s.size);
|
||||||
TOP() = VAR(Bytes(std::move(buffer)));
|
TOP() = VAR(Bytes(p, s.size));
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(BUILD_TUPLE)
|
TARGET(BUILD_TUPLE)
|
||||||
_0 = VAR(STACK_VIEW(byte.arg).to_tuple());
|
_0 = VAR(STACK_VIEW(byte.arg).to_tuple());
|
||||||
|
20
src/io.cpp
20
src/io.cpp
@ -32,12 +32,13 @@ Bytes _default_import_handler(const Str& name){
|
|||||||
FILE* fp = io_fopen(cname.c_str(), "rb");
|
FILE* fp = io_fopen(cname.c_str(), "rb");
|
||||||
if(!fp) return Bytes();
|
if(!fp) return Bytes();
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
std::vector<char> buffer(ftell(fp));
|
int buffer_size = ftell(fp);
|
||||||
|
unsigned char* buffer = new unsigned char[buffer_size];
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
size_t sz = io_fread(buffer.data(), 1, buffer.size(), fp);
|
size_t sz = io_fread(buffer, 1, buffer_size, fp);
|
||||||
PK_UNUSED(sz);
|
PK_UNUSED(sz);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return Bytes(std::move(buffer));
|
return Bytes(buffer, buffer_size);
|
||||||
#else
|
#else
|
||||||
return Bytes();
|
return Bytes();
|
||||||
#endif
|
#endif
|
||||||
@ -55,14 +56,13 @@ Bytes _default_import_handler(const Str& name){
|
|||||||
vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){
|
vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){
|
||||||
FileIO& io = CAST(FileIO&, args[0]);
|
FileIO& io = CAST(FileIO&, args[0]);
|
||||||
fseek(io.fp, 0, SEEK_END);
|
fseek(io.fp, 0, SEEK_END);
|
||||||
std::vector<char> buffer(ftell(io.fp));
|
int buffer_size = ftell(io.fp);
|
||||||
|
unsigned char* buffer = new unsigned char[buffer_size];
|
||||||
fseek(io.fp, 0, SEEK_SET);
|
fseek(io.fp, 0, SEEK_SET);
|
||||||
size_t sz = io_fread(buffer.data(), 1, buffer.size(), io.fp);
|
size_t actual_size = io_fread(buffer, 1, buffer_size, io.fp);
|
||||||
PK_ASSERT(sz <= buffer.size());
|
PK_ASSERT(actual_size <= buffer_size);
|
||||||
// in text mode, CR may be dropped, which may cause `sz < buffer.size()`
|
// in text mode, CR may be dropped, which may cause `actual_size < buffer_size`
|
||||||
if(sz < buffer.size()) buffer.resize(sz);
|
Bytes b(buffer, actual_size);
|
||||||
PK_UNUSED(sz);
|
|
||||||
Bytes b(std::move(buffer));
|
|
||||||
if(io.is_text()) return VAR(b.str());
|
if(io.is_text()) return VAR(b.str());
|
||||||
return VAR(std::move(b));
|
return VAR(std::move(b));
|
||||||
});
|
});
|
||||||
|
@ -653,9 +653,9 @@ void init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind_method<0>("str", "encode", [](VM* vm, ArgsView args) {
|
_vm->bind_method<0>("str", "encode", [](VM* vm, ArgsView args) {
|
||||||
const Str& self = _CAST(Str&, args[0]);
|
const Str& self = _CAST(Str&, args[0]);
|
||||||
std::vector<char> buffer(self.length());
|
unsigned char* buffer = new unsigned char[self.length()];
|
||||||
memcpy(buffer.data(), self.data, self.length());
|
memcpy(buffer, self.data, self.length());
|
||||||
return VAR(Bytes(std::move(buffer)));
|
return VAR(Bytes(buffer, self.length()));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) {
|
_vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) {
|
||||||
@ -1027,13 +1027,13 @@ void init_builtins(VM* _vm) {
|
|||||||
/************ bytes ************/
|
/************ bytes ************/
|
||||||
_vm->bind_constructor<2>("bytes", [](VM* vm, ArgsView args){
|
_vm->bind_constructor<2>("bytes", [](VM* vm, ArgsView args){
|
||||||
List& list = CAST(List&, args[1]);
|
List& list = CAST(List&, args[1]);
|
||||||
std::vector<char> buffer(list.size());
|
std::vector<unsigned char> buffer(list.size());
|
||||||
for(int i=0; i<list.size(); i++){
|
for(int i=0; i<list.size(); i++){
|
||||||
i64 b = CAST(i64, list[i]);
|
i64 b = CAST(i64, list[i]);
|
||||||
if(b<0 || b>255) vm->ValueError("byte must be in range[0, 256)");
|
if(b<0 || b>255) vm->ValueError("byte must be in range[0, 256)");
|
||||||
buffer[i] = (char)b;
|
buffer[i] = (char)b;
|
||||||
}
|
}
|
||||||
return VAR(Bytes(std::move(buffer)));
|
return VAR(Bytes(buffer));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__getitem__(_vm->tp_bytes, [](VM* vm, PyObject* obj, PyObject* index) {
|
_vm->bind__getitem__(_vm->tp_bytes, [](VM* vm, PyObject* obj, PyObject* index) {
|
||||||
@ -1045,7 +1045,7 @@ void init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind__hash__(_vm->tp_bytes, [](VM* vm, PyObject* obj) {
|
_vm->bind__hash__(_vm->tp_bytes, [](VM* vm, PyObject* obj) {
|
||||||
const Bytes& self = _CAST(Bytes&, obj);
|
const Bytes& self = _CAST(Bytes&, obj);
|
||||||
std::string_view view(self.data(), self.size());
|
std::string_view view((char*)self.data(), self.size());
|
||||||
return (i64)std::hash<std::string_view>()(view);
|
return (i64)std::hash<std::string_view>()(view);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user