summaryrefslogtreecommitdiff
path: root/tools/lz/merging.c
diff options
context:
space:
mode:
authoraaaaaa123456789 <aaaaaa123456789@acidch.at>2020-05-23 14:30:04 -0300
committerGitHub <noreply@github.com>2020-05-23 13:30:04 -0400
commit2b7237e299d5018e837bae550d18deeff3c7db7d (patch)
treef5ad065c573e8c16c99ca39f09b217a9cb7021d3 /tools/lz/merging.c
parentf1513ae8ad47c603abdba2749ef3e4e046817623 (diff)
Match LZ compressed files (#724)
Replace lzcomp with new version and match all LZ compressed files
Diffstat (limited to 'tools/lz/merging.c')
-rw-r--r--tools/lz/merging.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/tools/lz/merging.c b/tools/lz/merging.c
new file mode 100644
index 000000000..def572b15
--- /dev/null
+++ b/tools/lz/merging.c
@@ -0,0 +1,61 @@
+#include "proto.h"
+
+struct command * select_command_sequence (struct command ** sequences, const unsigned short * lengths, unsigned count, unsigned short * final_length) {
+ unsigned short min_sequence = 0, min_length = compressed_length(*sequences, *lengths);
+ unsigned short seq, len;
+ for (seq = 1; seq < count; seq ++) {
+ len = compressed_length(sequences[seq], lengths[seq]);
+ if (len < min_length) {
+ min_sequence = seq;
+ min_length = len;
+ }
+ }
+ *final_length = lengths[min_sequence];
+ struct command * current = malloc(*final_length * sizeof(struct command));
+ memcpy(current, sequences[min_sequence], *final_length * sizeof(struct command));
+ struct command * new;
+ for (seq = 1; seq < count; seq ++) {
+ new = merge_command_sequences(current, *final_length, sequences[(seq + min_sequence) % count], lengths[(seq + min_sequence) % count], final_length);
+ free(current);
+ current = new;
+ }
+ return current;
+}
+
+struct command * merge_command_sequences (const struct command * current, unsigned short current_length, const struct command * new, unsigned short new_length,
+ unsigned short * result_length) {
+ struct command * result = malloc(sizeof(struct command) * (current_length + new_length));
+ struct command * current_command = result;
+ const struct command * saved_current;
+ const struct command * saved_new;
+ unsigned short current_pos, new_pos;
+ while (current_length) {
+ if (current -> count == new -> count) {
+ *(current_command ++) = pick_best_command(2, *(current ++), *(new ++));
+ current_length --;
+ continue;
+ }
+ saved_current = current;
+ saved_new = new;
+ current_pos = (current ++) -> count;
+ new_pos = (new ++) -> count;
+ current_length --;
+ while (current_pos != new_pos)
+ if (current_pos < new_pos) {
+ current_pos += (current ++) -> count;
+ current_length --;
+ } else
+ new_pos += (new ++) -> count;
+ current_pos = compressed_length(saved_current, current - saved_current);
+ new_pos = compressed_length(saved_new, new - saved_new);
+ if (new_pos < current_pos) {
+ memcpy(current_command, saved_new, sizeof(struct command) * (new - saved_new));
+ current_command += new - saved_new;
+ } else {
+ memcpy(current_command, saved_current, sizeof(struct command) * (current - saved_current));
+ current_command += current - saved_current;
+ }
+ }
+ *result_length = current_command - result;
+ return result;
+}