summaryrefslogtreecommitdiffstats
path: root/server/glz_encode_match_tmpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/glz_encode_match_tmpl.c')
-rw-r--r--server/glz_encode_match_tmpl.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/server/glz_encode_match_tmpl.c b/server/glz_encode_match_tmpl.c
new file mode 100644
index 00000000..01427173
--- /dev/null
+++ b/server/glz_encode_match_tmpl.c
@@ -0,0 +1,151 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define SHORT_PIX_IMAGE_DIST_LEVEL_1 64 //(1 << 6)
+#define SHORT_PIX_IMAGE_DIST_LEVEL_2 16384 // (1 << 14)
+#define SHORT_PIX_IMAGE_DIST_LEVEL_3 4194304 // (1 << 22)
+#define FAR_PIX_IMAGE_DIST_LEVEL_1 256 // (1 << 8)
+#define FAR_PIX_IMAGE_DIST_LEVEL_2 65536 // (1 << 16)
+#define FAR_PIX_IMAGE_DIST_LEVEL_3 16777216 // (1 << 24)
+
+/* if image_distance = 0, pixel_distance is the distance between the matching pixels.
+ Otherwise, it is the offset from the beginning of the referred image */
+#if defined(GLZ_ENCODE_MATCH) /* actually perfroming the encoding */
+static INLINE void encode_match(Encoder *encoder, uint32_t image_distance,
+ size_t pixel_distance, size_t len)
+#elif defined(GLZ_ENCODE_SIZE) /* compute the size of the encoding except for the match length*/
+static INLINE int get_encode_ref_size(uint32_t image_distance, size_t pixel_distance)
+#endif
+{
+#if defined(GLZ_ENCODE_SIZE)
+ int encode_size;
+#endif
+
+#if defined(GLZ_ENCODE_MATCH)
+ /* encoding the match length + Long/Short dist bit + 12 LSB pixels of pixel_distance*/
+ if (len < 7) {
+ if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) {
+ encode(encoder, (uint8_t)((len << 5) + (pixel_distance & 0x0f)));
+ } else {
+ encode(encoder, (uint8_t)((len << 5) + 16 + (pixel_distance & 0x0f)));
+ }
+ encode(encoder, (uint8_t)((pixel_distance >> 4) & 255));
+ } else {
+ if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) {
+ encode(encoder, (uint8_t)((7 << 5) + (pixel_distance & 0x0f)));
+ } else {
+ encode(encoder, (uint8_t)((7 << 5) + 16 + (pixel_distance & 0x0f)));
+ }
+ for (len -= 7; len >= 255; len -= 255) {
+ encode(encoder, 255);
+ }
+ encode(encoder, (uint8_t)len);
+ encode(encoder, (uint8_t)((pixel_distance >> 4) & 255));
+ }
+#endif
+
+
+ /* encoding the rest of the pixel ditsance and the image_dist and its 2 control bits */
+
+ /* The first 2 MSB bits indicate how many more bytes should be read for image dist */
+ if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) {
+ if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_1) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder, (uint8_t)(image_distance & 0x3f));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 3;
+#endif
+ } else if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_2) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder, (uint8_t)((1 << 6) + (image_distance & 0x3f)));
+ encode(encoder, (uint8_t)((image_distance >> 6) & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 4;
+#endif
+ } else if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_3) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder, (uint8_t)((1 << 7) + (image_distance & 0x3f)));
+ encode(encoder, (uint8_t)((image_distance >> 6) & 255));
+ encode(encoder, (uint8_t)((image_distance >> 14) & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 5;
+#endif
+ } else {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder, (uint8_t)((1 << 7) + (1 << 6) + (image_distance & 0x3f)));
+ encode(encoder, (uint8_t)((image_distance >> 6) & 255));
+ encode(encoder, (uint8_t)((image_distance >> 14) & 255));
+ encode(encoder, (uint8_t)((image_distance >> 22) & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 6;
+#endif
+ }
+ } else {
+ /* the third MSB bit indicates if the pixel_distance is medium/long*/
+ uint8_t long_dist_control = (pixel_distance < MAX_PIXEL_MEDIUM_DISTANCE) ? 0 : 32;
+ if (image_distance == 0) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder, (uint8_t)(long_dist_control + ((pixel_distance >> 12) & 31)));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 3;
+#endif
+ } else if (image_distance < FAR_PIX_IMAGE_DIST_LEVEL_1) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder,
+ (uint8_t)(long_dist_control + (1 << 6) + ((pixel_distance >> 12) & 31)));
+ encode(encoder, (uint8_t)(image_distance & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 4;
+#endif
+ } else if (image_distance < FAR_PIX_IMAGE_DIST_LEVEL_2) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder,
+ (uint8_t)(long_dist_control + (1 << 7) + ((pixel_distance >> 12) & 31)));
+ encode(encoder, (uint8_t)(image_distance & 255));
+ encode(encoder, (uint8_t)((image_distance >> 8) & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 5;
+#endif
+ } else {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder,
+ (uint8_t)(long_dist_control + (1 << 7) + (1 << 6) +
+ ((pixel_distance >> 12) & 31)));
+ encode(encoder, (uint8_t)(image_distance & 255));
+ encode(encoder, (uint8_t)((image_distance >> 8) & 255));
+ encode(encoder, (uint8_t)((image_distance >> 16) & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size = 6;
+#endif
+ }
+
+ if (long_dist_control) {
+#if defined(GLZ_ENCODE_MATCH)
+ encode(encoder, (uint8_t)((pixel_distance >> 17) & 255));
+#elif defined(GLZ_ENCODE_SIZE)
+ encode_size++;
+#endif
+ }
+ }
+
+#if defined(GLZ_ENCODE_SIZE)
+ return encode_size;
+#endif
+}
+
+#undef GLZ_ENCODE_SIZE
+#undef GLZ_ENCODE_MATCH