replace format use of std::stringstream with sprintf

This commit is contained in:
blueloveTH 2024-01-20 22:27:32 +08:00
parent 0d78e54abe
commit 0af2855ce5
8 changed files with 101 additions and 49 deletions

View File

@ -48,9 +48,9 @@ struct VoidP{
bool operator>=(const VoidP& other) const { return ptr >= other.ptr; }
Str hex() const{
std::stringstream ss; // hex
ss << std::hex << reinterpret_cast<intptr_t>(ptr);
return "0x" + ss.str();
SStream ss;
ss.write_hex(ptr);
return ss.str();
}
static void _register(VM* vm, PyObject* mod, PyObject* type);

View File

@ -3,13 +3,11 @@
#include <cmath>
#include <cstring>
#include <sstream>
#include <stdexcept>
#include <vector>
#include <string>
#include <chrono>
#include <string_view>
#include <iomanip>
#include <memory>
#include <iostream>
#include <map>

View File

@ -127,37 +127,31 @@ struct SStream{
PK_ALWAYS_PASS_BY_POINTER(SStream)
// pod_vector<T> is allocated by pool64 so the buffer can be moved into Str without a copy
pod_vector<char> buffer;
int _precision = -1;
bool empty() const { return buffer.empty(); }
void setprecision(int precision) { _precision = precision; }
SStream(){}
SStream(int guess_size){ buffer.reserve(guess_size); }
Str str();
SStream& operator<<(const Str& s);
SStream& operator<<(const char* s);
SStream& operator<<(i64 val);
SStream& operator<<(const std::string& s);
SStream& operator<<(std::string_view s);
SStream& operator<<(char c);
SStream& operator<<(StrName sn);
void write_hex(unsigned char c);
SStream& operator<<(const Str&);
SStream& operator<<(const char*);
SStream& operator<<(int);
SStream& operator<<(unsigned int);
SStream& operator<<(unsigned long);
SStream& operator<<(i64);
SStream& operator<<(f64);
SStream& operator<<(const std::string&);
SStream& operator<<(std::string_view);
SStream& operator<<(char);
SStream& operator<<(StrName);
template<typename T>
SStream& operator<<(T val){
if constexpr(std::is_floating_point_v<T>){
if(std::isinf(val) || std::isnan(val)){
return (*this) << std::to_string(val);
}
std::stringstream ss; // float
ss << std::setprecision(std::numeric_limits<f64>::max_digits10-1) << val;
std::string s = ss.str();
if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0";
return (*this) << s;
}
(*this) << std::to_string(val);
return *this;
}
void write_hex(unsigned char);
void write_hex(void*);
void write_hex(i64);
};
template<typename... Args>

View File

@ -60,10 +60,12 @@ namespace pkpy{
char c = 0;
if(s[i]>='0' && s[i]<='9') c += s[i]-'0';
else if(s[i]>='A' && s[i]<='F') c += s[i]-'A'+10;
else if(s[i]>='a' && s[i]<='f') c += s[i]-'a'+10;
else vm->ValueError(fmt("invalid hex char: '", s[i], "'"));
c <<= 4;
if(s[i+1]>='0' && s[i+1]<='9') c += s[i+1]-'0';
else if(s[i+1]>='A' && s[i+1]<='F') c += s[i+1]-'A'+10;
else if(s[i+1]>='a' && s[i+1]<='f') c += s[i+1]-'a'+10;
else vm->ValueError(fmt("invalid hex char: '", s[i+1], "'"));
buffer.p[i/2] = c;
}

View File

@ -117,9 +117,9 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, PyVec2& currentVelocity, float
}, {}, BindType::STATICMETHOD);
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyVec2& self = _CAST(PyVec2&, obj);
std::stringstream ss;
ss << std::fixed << std::setprecision(3);
Vec2 self = _CAST(PyVec2&, obj);
SStream ss;
ss.setprecision(3);
ss << "vec2(" << self.x << ", " << self.y << ")";
return VAR(ss.str());
});
@ -165,9 +165,9 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, PyVec2& currentVelocity, float
});
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyVec3& self = _CAST(PyVec3&, obj);
std::stringstream ss;
ss << std::fixed << std::setprecision(3);
Vec3 self = _CAST(PyVec3&, obj);
SStream ss;
ss.setprecision(3);
ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
return VAR(ss.str());
});
@ -202,9 +202,9 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, PyVec2& currentVelocity, float
});
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyVec4& self = _CAST(PyVec4&, obj);
std::stringstream ss;
ss << std::fixed << std::setprecision(3);
Vec4 self = _CAST(PyVec4&, obj);
SStream ss;
ss.setprecision(3);
ss << "vec4(" << self.x << ", " << self.y << ", " << self.z << ", " << self.w << ")";
return VAR(ss.str());
});
@ -261,9 +261,9 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, PyVec2& currentVelocity, float
});
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyMat3x3& self = _CAST(PyMat3x3&, obj);
std::stringstream ss;
ss << std::fixed << std::setprecision(3);
const PyMat3x3& self = _CAST(PyMat3x3&, obj);
SStream ss;
ss.setprecision(3);
ss << "mat3x3([" << self._11 << ", " << self._12 << ", " << self._13 << ",\n";
ss << " " << self._21 << ", " << self._22 << ", " << self._23 << ",\n";
ss << " " << self._31 << ", " << self._32 << ", " << self._33 << "])";

View File

@ -254,9 +254,9 @@ void init_builtins(VM* _vm) {
});
_vm->bind_func<1>(_vm->builtins, "hex", [](VM* vm, ArgsView args) {
std::stringstream ss; // hex
ss << std::hex << CAST(i64, args[0]);
return VAR("0x" + ss.str());
SStream ss;
ss.write_hex(CAST(i64, args[0]));
return VAR(ss.str());
});
_vm->bind_func<1>(_vm->builtins, "iter", [](VM* vm, ArgsView args) {
@ -300,9 +300,10 @@ void init_builtins(VM* _vm) {
// tp_object
_vm->bind__repr__(VM::tp_object, [](VM* vm, PyObject* obj) {
if(is_tagged(obj)) PK_FATAL_ERROR();
std::stringstream ss; // hex
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at 0x";
ss << std::hex << reinterpret_cast<intptr_t>(obj) << ">";
SStream ss;
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
ss.write_hex(obj);
ss << ">";
return VAR(ss.str());
});

View File

@ -469,6 +469,19 @@ int utf8len(unsigned char c, bool suppress){
return *this << sn.sv();
}
SStream& SStream::operator<<(unsigned int val){
return (*this) << static_cast<i64>(val);
}
SStream& SStream::operator<<(unsigned long val){
// unsigned long could be out of range of `i64`, use `std::to_string` instead
return (*this) << std::to_string(val);
}
SStream& SStream::operator<<(int val){
return (*this) << static_cast<i64>(val);
}
SStream& SStream::operator<<(i64 val){
// str(-2**64).__len__() == 21
buffer.reserve(buffer.size() + 24);
@ -489,9 +502,53 @@ int utf8len(unsigned char c, bool suppress){
return *this;
}
SStream& SStream::operator<<(f64 val){
if(std::isinf(val) || std::isnan(val)){
return (*this) << std::to_string(val);
}
char b[32];
if(_precision == -1){
int prec = std::numeric_limits<f64>::max_digits10-1;
sprintf(b, "%.*g", prec, val);
}else{
int prec = _precision;
sprintf(b, "%.*f", prec, val);
}
(*this) << b;
if(std::all_of(b+1, b+strlen(b), isdigit)){
(*this) << ".0";
}
return *this;
}
void SStream::write_hex(unsigned char c){
*this << "0123456789ABCDEF"[c >> 4];
*this << "0123456789ABCDEF"[c & 0xf];
}
void SStream::write_hex(void* p){
(*this) << "0x";
uintptr_t p_t = reinterpret_cast<uintptr_t>(p);
for(int i=sizeof(void*)-1; i>=0; i--){
unsigned char cpnt = (p_t >> (i * 8)) & 0xff;
write_hex(cpnt);
}
}
void SStream::write_hex(i64 val){
if(val < 0){
(*this) << "-";
val = -val;
}
(*this) << "0x";
if(val == 0){
(*this) << "0";
return;
}
for(int i=56; i>=0; i-=8){
unsigned char cpnt = (val >> i) & 0xff;
if(cpnt != 0) write_hex(cpnt);
}
}
} // namespace pkpy

View File

@ -1,5 +1,4 @@
#include "pocketpy/vm.h"
#include "pocketpy/config.h"
namespace pkpy{
@ -507,8 +506,9 @@ PyObject* VM::_format_string(Str spec, PyObject* obj){
if(type == 'f'){
f64 val = CAST(f64, obj);
if(precision < 0) precision = 6;
std::stringstream ss; // float
ss << std::fixed << std::setprecision(precision) << val;
SStream ss;
ss.setprecision(precision);
ss << val;
ret = ss.str();
}else if(type == 'd'){
ret = std::to_string(CAST(i64, obj));