decompression uses less memory

This commit is contained in:
Gábor Poczkodi 2024-11-10 00:43:21 +01:00
parent a062a22e72
commit 96b61c73dc

View file

@ -15,18 +15,30 @@ void StoreYamlComponent::dump_config() {
} }
} }
struct Entry {
uint32_t p : 24;
uint32_t c : 8;
};
class Decompressor { class Decompressor {
std::map<uint16_t, std::string> codes_; // TODO: replace string with char + index to next char std::map<uint16_t, Entry> codes_;
size_t pos_{0}; size_t pos_;
uint8_t size_{0}; uint8_t size_;
uint32_t buff_{0}; uint32_t buff_;
size_t code_index_; size_t code_index_;
uint8_t code_width_; uint8_t code_width_;
Entry prev_;
public: public:
Decompressor() { Decompressor() { this->reset(); }
for (int i = 0; i < 256; i++) {
this->codes_[i] = std::string(1, (char) i); void reset() {
this->pos_ = 0;
this->size_ = 0;
this->buff_ = 0;
this->codes_.clear();
for (uint32_t i = 0; i < 256; i++) {
this->codes_[i] = Entry{.p = 0, .c = i};
} }
this->code_index_ = this->codes_.size(); this->code_index_ = this->codes_.size();
this->code_width_ = 9; // log2next + 1 this->code_width_ = 9; // log2next + 1
@ -47,40 +59,60 @@ class Decompressor {
return value; return value;
} }
std::string get_code() { const Entry *get_entry(uint16_t &code) {
if (this->code_index_ == ((1 << this->code_width_) - 1)) { if (this->code_index_ == ((1 << this->code_width_) - 1)) {
this->code_width_++; this->code_width_++;
} }
uint32_t c = get_bits(this->code_width_); code = (uint16_t) get_bits(this->code_width_);
auto i = this->codes_.find(c); auto i = this->codes_.find(code);
if (i != this->codes_.end()) { if (i != this->codes_.end()) {
return i->second; return &i->second;
} }
if (c != this->codes_.size()) { if (code != this->codes_.size()) {
this->pos_ = ESPHOME_YAML_SIZE; // error in input, set eof this->pos_ = ESPHOME_YAML_SIZE; // error in input, set eof
} }
return std::string(); return nullptr;
} }
void add_code(const std::string &c) { this->codes_[this->code_index_++] = c; }
bool is_eof() const { return this->pos_ >= ESPHOME_YAML_SIZE; } bool is_eof() const { return this->pos_ >= ESPHOME_YAML_SIZE; }
std::string get_string(const Entry *entry) const {
std::string s(1, (char) entry->c);
while (entry->p != 0) {
entry = &this->codes_.find(entry->p)->second;
s = std::string(1, (char) entry->c) + s;
}
return s;
}
std::string get_first() {
this->reset();
uint16_t code = 0;
const Entry *entry = this->get_entry(code);
std::string s = this->get_string(entry);
this->prev_.c = (uint32_t) s[0];
this->prev_.p = code;
return s;
}
std::string get_next() {
uint16_t code = 0;
const Entry *entry = this->get_entry(code);
if (entry == nullptr)
entry = &this->prev_;
std::string s = this->get_string(entry);
this->prev_.c = s[0];
this->codes_[this->code_index_++] = this->prev_;
this->prev_.p = code;
return s;
}
}; };
void StoreYamlComponent::log(bool dump_config) const { void StoreYamlComponent::log(bool dump_config) const {
Decompressor *dec = new Decompressor(); Decompressor *dec = new Decompressor();
std::string yaml = dec->get_first();
std::string c = dec->get_code();
std::string prev = c;
std::string yaml = c;
while (!dec->is_eof()) { while (!dec->is_eof()) {
std::string c = dec->get_code(); yaml += dec->get_next();
if (c.empty())
c = prev + prev[0];
dec->add_code(prev + c[0]);
prev = c;
yaml += c;
// print line by line because the logger cannot handle too much data // print line by line because the logger cannot handle too much data
// it also uses less memory // it also uses less memory
size_t newline = 0; size_t newline = 0;