strreplace: clean up and simplify
[profile/ivi/syslinux.git] / core / rllpack.c
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
4  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
9  *   Boston MA 02110-1301, USA; either version 2 of the License, or
10  *   (at your option) any later version; incorporated herein by reference.
11  *
12  * ----------------------------------------------------------------------- */
13
14 /*
15  * rllpack.inc
16  *
17  * Very simple RLL compressor/decompressor, used to pack binary structures
18  * together.
19  *
20  * Format of leading byte
21  * 1-128        = x verbatim bytes follow
22  * 129-223      = (x-126) times subsequent byte
23  * 224-255      = (x-224)*256+(next byte) times the following byte
24  * 0            = end of data
25  *
26  * These structures are stored *in reverse order* in high memory.
27  * High memory pointers point to one byte beyond the end.
28  */
29
30 #include <com32.h>
31 #include <stddef.h>
32 #include <string.h>
33
34 void rllpack(com32sys_t * regs)
35 {
36     uint8_t *i = (uint8_t *) (regs->esi.l);
37     uint8_t *o = (uint8_t *) (regs->edi.l);
38     size_t cnt = regs->ecx.l;
39     size_t run, vrun, tcnt;
40     uint8_t *hdr = NULL;
41     uint8_t c;
42
43     vrun = (size_t)-1;
44     while (cnt) {
45         c = *i;
46
47         run = 1;
48         tcnt = (cnt > 8191) ? 8191 : cnt;
49         while (run < tcnt && i[run] == c)
50             run++;
51
52         if (run < 3) {
53             if (vrun >= 128) {
54                 hdr = --o;
55                 vrun = 0;
56             }
57             *--o = c;
58             *hdr = ++vrun;
59             i++;
60             cnt--;
61         } else {
62             if (run < 224 - 126) {
63                 *--o = run + 126;
64             } else {
65                 o -= 2;
66                 *(uint16_t *) o = run + (224 << 8);
67             }
68             *--o = c;
69             vrun = (size_t)-1;
70             i += run;
71             cnt -= run;
72         }
73     }
74     *--o = 0;
75
76     regs->esi.l = (size_t)i;
77     regs->edi.l = (size_t)o;
78 }
79
80 void rllunpack(com32sys_t * regs)
81 {
82     uint8_t *i = (uint8_t *) regs->esi.l;
83     uint8_t *o = (uint8_t *) regs->edi.l;
84     uint8_t c;
85     size_t n;
86
87     while ((c = *--i)) {
88         if (c <= 128) {
89             while (c--)
90                 *o++ = *--i;
91         } else {
92             if (c < 224)
93                 n = c - 126;
94             else
95                 n = ((c - 224) << 8) + *--i;
96             c = *--i;
97             while (n--)
98                 *o++ = c;
99         }
100     }
101
102     regs->esi.l = (size_t)i;
103     regs->ecx.l = (size_t)o - regs->edi.l;
104     regs->edi.l = (size_t)o;
105 }