1010
1111#include " pawn/amx.h"
1212#include " pawn/amxpool.h"
13+ #include " pawn/heatshrink_decoder.h"
1314
1415namespace Pinetime {
1516 namespace Applications {
@@ -24,12 +25,18 @@ namespace Pinetime {
2425 return nullptr ;
2526 }
2627
27- virtual size_t Read (uint8_t * buffer, size_t size, size_t offset) = 0;
28+ virtual void Seek (size_t position) = 0;
29+ virtual size_t Read (uint8_t * buffer, size_t size) = 0;
30+
31+ size_t Read (uint8_t * buffer, size_t size, size_t position) {
32+ Seek (position);
33+ return Read (buffer, size);
34+ }
2835 };
2936
3037 class ConstFile : public File {
3138 const uint8_t * backing;
32- size_t size;
39+ size_t size, position ;
3340
3441 public:
3542 ConstFile (const uint8_t * backing, size_t size) : backing(backing), size(size) {
@@ -39,10 +46,17 @@ namespace Pinetime {
3946 return backing;
4047 }
4148
42- size_t Read (uint8_t * buffer, size_t size, size_t offset) override {
43- if (size + offset > this ->size )
49+ void Seek (size_t position) override {
50+ this ->position = position;
51+ }
52+
53+ size_t Read (uint8_t * buffer, size_t size) override {
54+ if (position >= this ->size )
4455 return 0 ;
45- memcpy (buffer, backing + offset, size);
56+ if (position + size > this ->size )
57+ size = this ->size - position;
58+ memcpy (buffer, backing + position, size);
59+ position += size;
4660 return size;
4761 }
4862 };
@@ -62,15 +76,76 @@ namespace Pinetime {
6276 fs.FileClose (&file);
6377 }
6478
65- size_t Read (uint8_t * buffer, size_t size, size_t offset) override {
79+ void Seek (size_t position) override {
80+ fs.FileSeek (&file, position);
81+ }
82+
83+ size_t Read (uint8_t * buffer, size_t size) override {
6684 if (!ok)
6785 return 0 ;
68-
69- fs.FileSeek (&file, offset);
7086 return fs.FileRead (&file, buffer, size);
7187 }
7288 };
7389
90+ class HeatshrinkFile : public File {
91+ std::unique_ptr<File> inner;
92+ heatshrink_decoder decoder;
93+
94+ size_t real_pos;
95+ uint8_t pending_inner_read[100 ];
96+ size_t pending_pos = 0 , pending_size = 0 ;
97+
98+ void Reset () {
99+ heatshrink_decoder_reset (&decoder);
100+ pending_size = 0 ;
101+ pending_pos = 0 ;
102+ real_pos = 0 ;
103+ inner->Seek (0 );
104+ }
105+
106+ public:
107+ HeatshrinkFile (std::unique_ptr<File> inner) : inner(std::move(inner)) {
108+ Reset ();
109+ }
110+
111+ /* *
112+ * Seek to a specified position in the *uncompressed* file.
113+ */
114+ void Seek (size_t position) override {
115+ if (position < this ->real_pos ) // We have to rewind
116+ Reset ();
117+
118+ uint8_t discard[50 ];
119+ while (this ->real_pos < position) {
120+ size_t remaining = position - this ->real_pos ;
121+ Read (discard, remaining > sizeof (discard) ? sizeof (discard) : remaining);
122+ }
123+ }
124+
125+ size_t Read (uint8_t * buffer, size_t size) override {
126+ size_t actual_read, total_read = 0 ;
127+
128+ while (total_read < size) {
129+ HSD_poll_res res = heatshrink_decoder_poll (&decoder, buffer + total_read, size - total_read, &actual_read);
130+ total_read += actual_read;
131+ real_pos += actual_read;
132+
133+ if (res == HSDR_POLL_EMPTY) {
134+ if (pending_size == 0 ) {
135+ pending_size = inner->Read (pending_inner_read, sizeof (pending_inner_read));
136+ pending_pos = 0 ;
137+ }
138+
139+ heatshrink_decoder_sink (&decoder, pending_inner_read + pending_pos, pending_size, &actual_read);
140+ pending_size -= actual_read;
141+ pending_pos += actual_read;
142+ }
143+ }
144+
145+ return total_read;
146+ }
147+ };
148+
74149 Pawn (AppControllers& controllers);
75150 Pawn (AppControllers& controllers, std::unique_ptr<File> file);
76151 ~Pawn () override ;
0 commit comments