Skip to content

Commit 47e06a8

Browse files
committed
Merge branch 'compression' into devel
* Fixed bug in determining file size for Unix-like systems. * Several optimizations of standard compression algorithm.
2 parents a47fa20 + 0166ba5 commit 47e06a8

File tree

10 files changed

+551
-174
lines changed

10 files changed

+551
-174
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*******************************************************************************
44

55
=== 1.0.29 ===
6+
* Fixed bug in determining file size for Unix-like systems.
7+
* Several optimizations of standard compression algorithm.
68
* Fixed bug in associativity of add, sub, mul, div and bit-and expressions.
79
* Added MacOS CI builds.
810

include/lsp-plug.in/resource/buffer.h

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (C) 2021 Linux Studio Plugins Project <https://lsp-plug.in/>
3-
* (C) 2021 Vladimir Sadovnikov <[email protected]>
2+
* Copyright (C) 2025 Linux Studio Plugins Project <https://lsp-plug.in/>
3+
* (C) 2025 Vladimir Sadovnikov <[email protected]>
44
*
55
* This file is part of lsp-runtime-lib
66
* Created on: 13 мар. 2021 г.
@@ -54,9 +54,10 @@ namespace lsp
5454
public:
5555
uint8_t *data; // Buffer data (2 x capacity)
5656
uint32_t *index; // Index
57-
ssize_t head; // Head of the buffer
58-
ssize_t tail; // Buffer tail
59-
ssize_t cap; // Buffer capacity
57+
uint32_t *root; // Root index
58+
uint32_t head; // Head of the buffer
59+
uint32_t length; // Buffer length
60+
uint32_t cap; // Buffer capacity
6061

6162
public:
6263
explicit cbuffer_t();
@@ -66,11 +67,38 @@ namespace lsp
6667
void destroy();
6768

6869
public:
69-
void append(const void *src, ssize_t count);
70+
/**
71+
* Append buffer to compression buffer
72+
* @param src buffer to append
73+
* @param count the length of the buffer to append
74+
*/
75+
void append(const void *src, size_t count);
76+
77+
/**
78+
* Append single byte to compression buffer
79+
* @param v byte to append
80+
*/
7081
void append(uint8_t v);
71-
size_t lookup(ssize_t *out, const void *src, size_t avail);
82+
83+
/**
84+
* Lookup for byte sequence inside of the buffer
85+
* @param out relative offset of the sub-sequence in the buffer to the last byte stored in the buffer
86+
* @param src byte sequence to search inside of the buffer
87+
* @param avail number of bytes available in the sequence
88+
* @return the length of sub-sequence found in the buffer
89+
*/
90+
size_t lookup(size_t *out, const void *src, size_t avail);
91+
92+
/**
93+
* Cleanup state of the buffer
94+
*/
7295
void clear();
73-
inline size_t size() const { return tail - head; }
96+
97+
/**
98+
* Get size of data currently stored in the buffer
99+
* @return size of data currently stored in the buffer
100+
*/
101+
inline size_t size() const { return lsp_min(length, cap); }
74102

75103
} cbuffer_t;
76104

@@ -81,9 +109,9 @@ namespace lsp
81109
{
82110
public:
83111
uint8_t *data; // Buffer data (2 x capacity)
84-
ssize_t head; // Head of the buffer
85-
ssize_t tail; // Buffer tail
86-
ssize_t cap; // Buffer capacity
112+
uint32_t length; // Actual size of buffer
113+
uint32_t head; // Head of the buffer
114+
uint32_t cap; // Buffer capacity
87115

88116
public:
89117
explicit dbuffer_t();
@@ -93,14 +121,43 @@ namespace lsp
93121
void destroy();
94122

95123
public:
124+
/**
125+
* Extract data from buffer
126+
* @param dst destination pointer to store result
127+
* @param offset relative offset of the subsequence in the buffer to the last byte store in the buffer
128+
* @param count number of bytes to extract
129+
* @return status of operation (error on buffer underflow)
130+
*/
131+
status_t extract(void *dst, size_t offset, size_t count);
132+
133+
/**
134+
* Append multiple bytes to the buffer
135+
* @param src data to append to the buffer
136+
* @param count number of bytes to append
137+
*/
96138
void append(const void *src, ssize_t count);
139+
140+
/**
141+
* Append single byte to the buffer
142+
* @param v byt to append
143+
*/
97144
void append(uint8_t v);
145+
146+
/**
147+
* Clear buffer state
148+
*/
98149
void clear();
99-
inline size_t size() const { return tail - head; }
150+
151+
/**
152+
* Get size of data currently stored in the buffer
153+
* @return size of data currently stored in the buffer
154+
*/
155+
inline size_t size() const { return length; }
100156

101157
} duffer_t;
102-
}
103-
}
158+
159+
} /* namespace resource */
160+
} /* namespace lsp */
104161

105162

106163

src/main/io/OutBitStream.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ namespace lsp
234234

235235
size_t written = 0;
236236

237-
#if defined(ARCH_X86)
237+
#ifdef LSP_UNALIGNED_MEMORY_SAFE
238238
// x86 allows unaligned access, write with machine words first
239239
const umword_t *wptr = reinterpret_cast<const umword_t *>(buf);
240240
size_t blocks = count & (~(sizeof(umword_t) - 1));
@@ -250,7 +250,7 @@ namespace lsp
250250
}
251251

252252
buf = wptr;
253-
#endif /* ARCH_X86 */
253+
#endif /* LSP_UNALIGNED_MEMORY_SAFE */
254254

255255
// Write the rest data with bytes
256256
const uint8_t *bptr = reinterpret_cast<const uint8_t *>(buf);
@@ -274,7 +274,7 @@ namespace lsp
274274

275275
size_t written = 0;
276276

277-
#if defined(ARCH_X86)
277+
#ifdef LSP_UNALIGNED_MEMORY_SAFE
278278
// x86 allows unaligned memory access, write with machine words first
279279
const umword_t *wptr = reinterpret_cast<const umword_t *>(buf);
280280
size_t blocks = bits & (~((sizeof(umword_t) << 3) - 1));
@@ -289,7 +289,7 @@ namespace lsp
289289
}
290290

291291
buf = wptr;
292-
#endif
292+
#endif /* LSP_UNALIGNED_MEMORY_SAFE */
293293

294294
// Write the rest data with bytes
295295
const uint8_t *bptr = reinterpret_cast<const uint8_t *>(buf);

src/main/io/Path.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (C) 2024 Linux Studio Plugins Project <https://lsp-plug.in/>
3-
* (C) 2024 Vladimir Sadovnikov <[email protected]>
2+
* Copyright (C) 2025 Linux Studio Plugins Project <https://lsp-plug.in/>
3+
* (C) 2025 Vladimir Sadovnikov <[email protected]>
44
*
55
* This file is part of lsp-runtime-lib
66
* Created on: 8 февр. 2019 г.
@@ -1601,7 +1601,7 @@ namespace lsp
16011601
{
16021602
fattr_t attr;
16031603
status_t res = File::stat(&sPath, &attr);
1604-
return (res != STATUS_OK) ? attr.size : -res;
1604+
return (res == STATUS_OK) ? attr.size : -res;
16051605
}
16061606

16071607
bool Path::exists() const

src/main/resource/Compressor.cpp

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ namespace lsp
200200
status_t res = STATUS_OK;
201201
const uint8_t *head = sTemp.data();
202202
const uint8_t *tail = &head[flength];
203-
ssize_t offset = 0, length = 0, append = 0;
204-
size_t rep = 0;
203+
size_t offset = 0;
205204

206205
// IF_TRACE(
207206
// wssize_t coffset = sOS.position();
@@ -213,38 +212,32 @@ namespace lsp
213212
while (head < tail)
214213
{
215214
// Estimate the length of match
216-
length = sBuffer.lookup(&offset, head, tail-head);
217-
if (length == 0)
218-
length = 1;
215+
size_t length = sBuffer.lookup(&offset, head, tail-head);
216+
const size_t emit = lsp_max(length, 1u);
219217

220218
// Calc number of repeats
221-
rep = calc_repeats(&head[length], tail);
222-
append = length + lsp_min(rep, REPEAT_BUF_MAX);
219+
size_t rep = calc_repeats(&head[emit], tail);
220+
size_t append = emit + lsp_min(rep, REPEAT_BUF_MAX);
223221

224222
// Estimate size of output
225-
size_t est1 = (est_uint(sBuffer.size() + *head, 5, 5) + est_uint(rep, 0, 4)) * length; // How many bits per octet
226-
size_t est2 = (offset < 0) ? est1 + 1 :
227-
est_uint(offset, 5, 5) +
228-
est_uint(length - 1, 5, 5) +
229-
est_uint(rep, 0, 4);
223+
const size_t est1 = est_uint(sBuffer.size() + *head, 5, 5) * length; // How many bits used to emit octet command
224+
const size_t est2 = (length > 0) ? est_uint(offset, 5, 5) + est_uint(emit - 1, 5, 5) : est1 + 1; // How many bits used to encode buffer replay command
230225

231-
if (est1 > est2) // Prefer buffer over dictionary
226+
// IF_TRACE(
227+
// if (rep)
228+
// ++ repeats;
229+
// )
230+
231+
if (est2 < est1) // Prefer buffer replay over octet emission
232232
{
233-
// REPLAY
234-
// Offset
233+
// REPLAY BUFFER
234+
// Emit Offset
235235
if ((res = emit_uint(offset, 5, 5)) != STATUS_OK)
236236
break;
237-
// Length
238-
if ((res = emit_uint(length - 1, 5, 5)) != STATUS_OK)
239-
break;
240-
// Repeat
241-
if ((res = emit_uint(rep, 0, 4)) != STATUS_OK)
237+
// Emit Length - 1
238+
if ((res = emit_uint(emit - 1, 5, 5)) != STATUS_OK)
242239
break;
243240

244-
// Append data to buffer
245-
sBuffer.append(head, append);
246-
head += length + rep;
247-
248241
// IF_TRACE(
249242
// ++ replays;
250243
// if (rep)
@@ -253,20 +246,22 @@ namespace lsp
253246
}
254247
else
255248
{
256-
// OCTET
257-
// Value
249+
// EMIT OCTET
250+
// Emit Value
258251
if ((res = emit_uint(sBuffer.size() + *head, 5, 5)) != STATUS_OK)
259252
break;
260-
// Repeat
261-
if ((res = emit_uint(rep, 0, 4)) != STATUS_OK)
262-
break;
263-
264-
// Append data to buffer
265-
sBuffer.append(head, append);
266-
head += length + rep;
267253

268254
// IF_TRACE(++octets);
269255
}
256+
257+
// Emit Repeat counter
258+
if ((res = emit_uint(rep, 0, 4)) != STATUS_OK)
259+
break;
260+
261+
262+
// Append data to buffer
263+
sBuffer.append(head, append);
264+
head += emit + rep;
270265
}
271266

272267
// Flush the bit sequence

src/main/resource/Decompressor.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ namespace lsp
137137
// Need to allocate data?
138138
if ((sReplay.cap < count) || (sReplay.data == NULL))
139139
{
140-
size_t cap = align_size(count, BUFFER_QUANTITY);
140+
size_t cap = align_size(lsp_max(sReplay.cap + (sReplay.cap >> 1), count), BUFFER_QUANTITY);
141141
uint8_t *ptr = reinterpret_cast<uint8_t *>(realloc(sReplay.data, cap));
142142
if (ptr == NULL)
143143
return STATUS_NO_MEM;
@@ -147,7 +147,10 @@ namespace lsp
147147
}
148148

149149
// Copy data to replay buffer
150-
memcpy(sReplay.data, &sBuffer.data[sBuffer.head + off], count);
150+
status_t res = sBuffer.extract(sReplay.data, off, count);
151+
if (res != STATUS_OK)
152+
return res;
153+
151154
sReplay.off = 0;
152155
sReplay.size = count;
153156
sReplay.rep = rep;
@@ -235,7 +238,7 @@ namespace lsp
235238

236239
if (offset < sBuffer.size())
237240
{
238-
// REPLAY
241+
// REPLAY BUFFER
239242
// Length
240243
if ((res = read_uint(&length, 5, 5)) != STATUS_OK)
241244
return res;
@@ -255,7 +258,7 @@ namespace lsp
255258
}
256259
else
257260
{
258-
// OCTET
261+
// EMIT OCTET
259262
// Repeat
260263
if ((res = read_uint(&rep, 0, 4)) != STATUS_OK)
261264
return res;

0 commit comments

Comments
 (0)