-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LZ4 format not compatible? #43
Comments
I don't know anything about Apple's LZ4_RAW, but it definitely should be compatible with the reference implementation. Do you have any specific examples of incompatibility? |
Ok, here's some details. Consider the following example using upstream -(void)testCompression {
auto string = std::string("HALLO HALLO HALLO HALLO HALLO HALLO HALLO HALLO HALLO HALLO");
uint8_t buffer[100];
auto compressed = ::LZ4_compress_default(string.c_str(), (char*)buffer, int(string.end() - string.begin()), sizeof(buffer));
for (int i = 0; i < compressed; ++i) {
printf("%02X, ", buffer[i]);
}
printf("\n");
} This prints out A corresponding Swift program: import SWCompression
import Foundation
let string = "HALLO HALLO HALLO HALLO HALLO HALLO HALLO HALLO HALLO HALLO"
let data = string.data(using: .utf8)!
let compressed = LZ4.compress(data: data)
for byte in compressed {
print(String(format: "%02X, ", byte), terminator: "")
}
print("") emits It looks like your algorithm implementation is appending/prepending some metadata. |
Right, the function To quote LZ4 manual:
As such, to obtain the exact same output from the reference implementation, you would need to use a function from lz4frame.h. |
I see. Would it be possible to add a parameter to your implementation so that we can choose the output format between frames and blocks? |
I am not sure there is any value in choosing between frames and blocks. There are various configurable parameters of the LZ4 algorithm (block size, block dependency, dictionary compression) that can result in different outputs (which may even include different amount of blocks themselves!) for the same input. So to decompress any isolated block you would still need to provide some external knowledge to the decompressor about how these blocks were compressed. At this point you would be reimplementing (at least, partially) the LZ4 frame format but in some other form. So my question to you, why do you require the capability to compress into blocks? If you would like to reduce the size of the output, you can have a look at this function. By default, |
I'm using LZ4 to compress/uncompress binary protocol data that is sent to a micro-controller (ESP32) via BLE. Every saved byte is valuable in this scenario. The central (iOS) would be using |
Hmm, I see. I will think about adding such functionality in the future.
Generally, it is not. As I mentioned before one input may result in creation of several blocks. This can happen if the input is "sufficiently large", the precise definition of which depends on your uncompressed block size settings. In SWCompression by default the block size is 4MB, which incidentally is the strict upper limit of the reference implementation on the block size. I do wonder what the aforementioned Meanwhile, assuming that size of your input is always smaller than 4MB and the input is always compressible, I can suggest the following workaround to extract only block data: let data = // ... data.count must be smaller than 4 * 1024 * 1024
let compressedData = LZ4.compress(data: data)
let block = compressedData[(compressedData.startIndex + 11)..<(compressedData.endIndex - 8)] |
Awesome, that's a quick fix that will do it for now. Thanks a lot. |
For some reason, it looks like the version of LZ4 you have implemented seems not compatible with Apple's LZ4_RAW or the reference implementation at https://github.com/lz4/lz4. Is that possible or am I using it wrong?
The text was updated successfully, but these errors were encountered: