| 96 | */ |
| 97 | |
| 98 | unsigned int |
| 99 | lzf_compress (const void *const in_data, unsigned int in_len, |
| 100 | void *out_data, unsigned int out_len |
| 101 | #if LZF_STATE_ARG |
| 102 | , LZF_STATE htab |
| 103 | #endif |
| 104 | ) |
| 105 | { |
| 106 | #if !LZF_STATE_ARG |
| 107 | LZF_STATE htab; |
| 108 | #endif |
| 109 | const u8 *ip = (const u8 *)in_data; |
| 110 | u8 *op = (u8 *)out_data; |
| 111 | const u8 *in_end = ip + in_len; |
| 112 | u8 *out_end = op + out_len; |
| 113 | const u8 *ref; |
| 114 | |
| 115 | /* off requires a type wide enough to hold a general pointer difference. |
| 116 | * ISO C doesn't have that (size_t might not be enough and ptrdiff_t only |
| 117 | * works for differences within a single object). We also assume that no |
| 118 | * no bit pattern traps. Since the only platform that is both non-POSIX |
| 119 | * and fails to support both assumptions is windows 64 bit, we make a |
| 120 | * special workaround for it. |
| 121 | */ |
| 122 | #if defined (WIN32) && defined (_M_X64) |
| 123 | unsigned _int64 off; /* workaround for missing POSIX compliance */ |
| 124 | #else |
| 125 | unsigned long off; |
| 126 | #endif |
| 127 | unsigned int hval; |
| 128 | int lit; |
| 129 | |
| 130 | if (!in_len || !out_len) |
| 131 | return 0; |
| 132 | |
| 133 | #if INIT_HTAB |
| 134 | memset (htab, 0, sizeof (htab)); |
| 135 | #endif |
| 136 | |
| 137 | lit = 0; op++; /* start run */ |
| 138 | |
| 139 | hval = FRST (ip); |
| 140 | while (ip < in_end - 2) |
| 141 | { |
| 142 | LZF_HSLOT *hslot; |
| 143 | |
| 144 | hval = NEXT (hval, ip); |
| 145 | hslot = htab + IDX (hval); |
| 146 | ref = *hslot + LZF_HSLOT_BIAS; *hslot = ip - LZF_HSLOT_BIAS; |
| 147 | |
| 148 | if (1 |
| 149 | #if INIT_HTAB |
| 150 | && ref < ip /* the next test will actually take care of this, but this is faster */ |
| 151 | #endif |
| 152 | && (off = ip - ref - 1) < MAX_OFF |
| 153 | && ref > (u8 *)in_data |
| 154 | && ref[2] == ip[2] |
| 155 | #if STRICT_ALIGN |
no test coverage detected