Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
lzss.h
Go to the documentation of this file.
1 /* Copyright 2015 the unarr project authors (see AUTHORS file).
2  License: LGPLv3 */
3 
4 /* adapted from https://code.google.com/p/theunarchiver/source/browse/XADMaster/LZSS.h */
5 
6 #ifndef rar_lzss_h
7 #define rar_lzss_h
8 
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <string.h>
13 
14 #if defined(_MSC_VER) && !defined(inline)
15 #define inline __inline
16 #endif
17 
18 typedef struct {
19  uint8_t *window;
20  int mask;
21  int64_t position;
22 } LZSS;
23 
24 static inline int64_t lzss_position(LZSS *self) { return self->position; }
25 
26 static inline int lzss_mask(LZSS *self) { return self->mask; }
27 
28 static inline int lzss_size(LZSS *self) { return self->mask + 1; }
29 
30 static inline uint8_t *lzss_window_pointer(LZSS *self) { return self->window; }
31 
32 static inline int lzss_offset_for_position(LZSS *self, int64_t pos) { return (int)(pos & self->mask); }
33 
34 static inline uint8_t *lzss_window_pointer_for_position(LZSS *self, int64_t pos) { return &self->window[lzss_offset_for_position(self, pos)]; }
35 
36 static inline int lzss_current_window_offset(LZSS *self) { return lzss_offset_for_position(self, self->position); }
37 
38 static inline uint8_t *lzss_current_window_pointer(LZSS *self) { return lzss_window_pointer_for_position(self, self->position); }
39 
40 static inline int64_t lzss_next_window_edge_after_position(LZSS *self, int64_t pos) { return (pos + lzss_size(self)) & ~(int64_t)lzss_mask(self); }
41 
42 static inline int64_t lzss_next_window_edge(LZSS *self) { return lzss_next_window_edge_after_position(self, self->position); }
43 
44 static inline uint8_t lzss_get_byte_from_window(LZSS *self, int64_t pos) { return *lzss_window_pointer_for_position(self, pos); }
45 
46 static inline void lzss_emit_literal(LZSS *self, uint8_t literal) {
47  /* self->window[(self->position & self->mask)] = literal; */
48  *lzss_current_window_pointer(self) = literal;
49  self->position++;
50 }
51 
52 static inline void lzss_emit_match(LZSS *self, int offset, int length) {
53  int windowoffs = lzss_current_window_offset(self);
54  int i;
55  for (i = 0; i < length; i++) {
56  self->window[(windowoffs + i) & lzss_mask(self)] = self->window[(windowoffs + i - offset) & lzss_mask(self)];
57  }
58  self->position += length;
59 }
60 
61 static inline void lzss_copy_bytes_from_window(LZSS *self, uint8_t *buffer, int64_t startpos, int length) {
62  int windowoffs = lzss_offset_for_position(self, startpos);
63  int firstpart = lzss_size(self) - windowoffs;
64  if (length <= firstpart) {
65  /* Request fits inside window */
66  memcpy(buffer, &self->window[windowoffs], length);
67  }
68  else {
69  /* Request wraps around window */
70  memcpy(buffer, &self->window[windowoffs], firstpart);
71  memcpy(buffer + firstpart, &self->window[0], length - firstpart);
72  }
73 }
74 
75 static inline bool lzss_initialize(LZSS *self, int windowsize) {
76  self->window = malloc(windowsize);
77  if (!self->window)
78  return false;
79 
80  self->mask = windowsize - 1; /* Assume windows are power-of-two sized! */
81  memset(self->window, 0, lzss_size(self));
82  self->position = 0;
83  return true;
84 }
85 
86 static inline void lzss_cleanup(LZSS *self) { free(self->window); }
87 
88 #endif