91static std::vector<std::uint8_t>
read_file(
const std::string& path) {
92 std::ifstream file(path, std::ios::binary | std::ios::ate);
97 std::streamsize size = file.tellg();
98 file.seekg(0, std::ios::beg);
100 std::vector<std::uint8_t> buffer(
static_cast<std::size_t
>(size));
101 if (!file.read(
reinterpret_cast<char*
>(buffer.data()), size)) {
117static int do_compress(
const char* input_path,
int packet_size,
int pt_period,
int ft_period,
118 int rt_period,
int robustness) {
121 if (input_data.empty()) {
122 std::fprintf(stderr,
"Error: Cannot read input file: %s\n", input_path);
126 std::size_t input_size = input_data.size();
128 if ((input_size %
static_cast<std::size_t
>(packet_size)) != 0) {
129 std::fprintf(stderr,
"Error: Input size (%zu) not divisible by packet size (%d)\n",
130 input_size, packet_size);
135 std::string output_path = std::string(input_path) +
".pkt";
138 std::vector<std::uint8_t> output_data(input_size * 2);
139 std::size_t output_size = 0;
143 if (packet_size == 90) {
144 result = compress<720>(
145 input_data.data(), input_size, output_data.data(), output_data.size(), output_size,
146 static_cast<std::uint8_t
>(robustness), pt_period, ft_period, rt_period);
148 std::fprintf(stderr,
"Error: Only 90-byte packets supported in CLI\n");
152 if (result != Error::Ok) {
153 std::fprintf(stderr,
"Error: Compression failed with code %d\n",
static_cast<int>(result));
158 if (!
write_file(output_path, output_data.data(), output_size)) {
159 std::fprintf(stderr,
"Error: Cannot write output file: %s\n", output_path.c_str());
164 std::size_t num_packets = input_size /
static_cast<std::size_t
>(packet_size);
165 double ratio =
static_cast<double>(input_size) /
static_cast<double>(output_size);
166 std::printf(
"Input: %s (%zu bytes, %zu packets)\n", input_path, input_size, num_packets);
167 std::printf(
"Output: %s (%zu bytes)\n", output_path.c_str(), output_size);
168 std::printf(
"Ratio: %.2fx\n", ratio);
169 std::printf(
"Parameters: R=%d, pt=%d, ft=%d, rt=%d\n", robustness, pt_period, ft_period,
175static int do_decompress(
const char* input_path,
int packet_size,
int robustness) {
178 if (input_data.empty()) {
179 std::fprintf(stderr,
"Error: Cannot read input file: %s\n", input_path);
183 std::size_t input_size = input_data.size();
189 std::vector<std::uint8_t> output_data(input_size * 20);
190 std::size_t output_size = 0;
194 if (packet_size == 90) {
196 decompress<720>(input_data.data(), input_size, output_data.data(), output_data.size(),
197 output_size,
static_cast<std::uint8_t
>(robustness));
199 std::fprintf(stderr,
"Error: Only 90-byte packets supported in CLI\n");
203 if (result != Error::Ok) {
204 std::fprintf(stderr,
"Error: Decompression failed with code %d\n",
205 static_cast<int>(result));
210 if (!
write_file(output_path, output_data.data(), output_size)) {
211 std::fprintf(stderr,
"Error: Cannot write output file: %s\n", output_path.c_str());
216 std::size_t num_packets = output_size /
static_cast<std::size_t
>(packet_size);
217 double ratio =
static_cast<double>(output_size) /
static_cast<double>(input_size);
218 std::printf(
"Input: %s (%zu bytes)\n", input_path, input_size);
219 std::printf(
"Output: %s (%zu bytes, %zu packets)\n", output_path.c_str(), output_size,
221 std::printf(
"Expansion: %.2fx\n", ratio);
222 std::printf(
"Parameters: packet_size=%d, R=%d\n", packet_size, robustness);
227int main(
int argc,
char** argv) {
228 bool decompress_mode =
false;
232 if (argc < 2 || std::strcmp(argv[1],
"-h") == 0 || std::strcmp(argv[1],
"--help") == 0) {
234 return (argc < 2) ? 1 : 0;
238 if (std::strcmp(argv[1],
"-v") == 0 || std::strcmp(argv[1],
"--version") == 0) {
244 if (std::strcmp(argv[1],
"-d") == 0) {
245 decompress_mode =
true;
249 if (decompress_mode) {
252 std::fprintf(stderr,
"Error: Decompress requires 3 arguments after -d\n");
253 std::fprintf(stderr,
"Usage: %s -d <input.pkt> <packet_size> <robustness>\n", argv[0]);
257 const char* input_path = argv[arg_offset];
258 int packet_size = std::atoi(argv[arg_offset + 1]);
259 int robustness = std::atoi(argv[arg_offset + 2]);
262 if (packet_size <= 0 || packet_size > 8192) {
263 std::fprintf(stderr,
"Error: packet_size must be 1-8192 bytes\n");
266 if (robustness < 0 || robustness > 7) {
267 std::fprintf(stderr,
"Error: robustness must be 0-7\n");
276 std::fprintf(stderr,
"Error: Compress requires 6 arguments\n");
277 std::fprintf(stderr,
"Usage: %s <input> <packet_size> <pt> <ft> <rt> <robustness>\n",
282 const char* input_path = argv[1];
283 int packet_size = std::atoi(argv[2]);
284 int pt_period = std::atoi(argv[3]);
285 int ft_period = std::atoi(argv[4]);
286 int rt_period = std::atoi(argv[5]);
287 int robustness = std::atoi(argv[6]);
290 if (packet_size <= 0 || packet_size > 8192) {
291 std::fprintf(stderr,
"Error: packet_size must be 1-8192 bytes\n");
294 if (robustness < 0 || robustness > 7) {
295 std::fprintf(stderr,
"Error: robustness must be 0-7\n");
298 if (pt_period <= 0 || ft_period <= 0 || rt_period <= 0) {
299 std::fprintf(stderr,
"Error: periods must be positive\n");
303 return do_compress(input_path, packet_size, pt_period, ft_period, rt_period, robustness);
static int do_compress(const char *input_path, int packet_size, int pt_period, int ft_period, int rt_period, int robustness)