File indexing completed on 2025-02-02 04:26:01
0001 /* Copyright 2015 the unarr project authors (see AUTHORS file). 0002 License: LGPLv3 */ 0003 0004 /* adapted from https://code.google.com/p/theunarchiver/source/browse/XADMaster/LZSS.h */ 0005 0006 #ifndef rar_lzss_h 0007 #define rar_lzss_h 0008 0009 #include <stdlib.h> 0010 #include <stdint.h> 0011 #include <stdbool.h> 0012 #include <string.h> 0013 0014 #if defined(_MSC_VER) && !defined(inline) 0015 #define inline __inline 0016 #endif 0017 0018 typedef struct { 0019 uint8_t *window; 0020 int mask; 0021 int64_t position; 0022 } LZSS; 0023 0024 static inline int64_t lzss_position(LZSS *self) { return self->position; } 0025 0026 static inline int lzss_mask(LZSS *self) { return self->mask; } 0027 0028 static inline int lzss_size(LZSS *self) { return self->mask + 1; } 0029 0030 static inline uint8_t *lzss_window_pointer(LZSS *self) { return self->window; } 0031 0032 static inline int lzss_offset_for_position(LZSS *self, int64_t pos) { return (int)(pos & self->mask); } 0033 0034 static inline uint8_t *lzss_window_pointer_for_position(LZSS *self, int64_t pos) { return &self->window[lzss_offset_for_position(self, pos)]; } 0035 0036 static inline int lzss_current_window_offset(LZSS *self) { return lzss_offset_for_position(self, self->position); } 0037 0038 static inline uint8_t *lzss_current_window_pointer(LZSS *self) { return lzss_window_pointer_for_position(self, self->position); } 0039 0040 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); } 0041 0042 static inline int64_t lzss_next_window_edge(LZSS *self) { return lzss_next_window_edge_after_position(self, self->position); } 0043 0044 static inline uint8_t lzss_get_byte_from_window(LZSS *self, int64_t pos) { return *lzss_window_pointer_for_position(self, pos); } 0045 0046 static inline void lzss_emit_literal(LZSS *self, uint8_t literal) { 0047 /* self->window[(self->position & self->mask)] = literal; */ 0048 *lzss_current_window_pointer(self) = literal; 0049 self->position++; 0050 } 0051 0052 static inline void lzss_emit_match(LZSS *self, int offset, int length) { 0053 int windowoffs = lzss_current_window_offset(self); 0054 int i; 0055 for (i = 0; i < length; i++) { 0056 self->window[(windowoffs + i) & lzss_mask(self)] = self->window[(windowoffs + i - offset) & lzss_mask(self)]; 0057 } 0058 self->position += length; 0059 } 0060 0061 static inline void lzss_copy_bytes_from_window(LZSS *self, uint8_t *buffer, int64_t startpos, int length) { 0062 int windowoffs = lzss_offset_for_position(self, startpos); 0063 int firstpart = lzss_size(self) - windowoffs; 0064 if (length <= firstpart) { 0065 /* Request fits inside window */ 0066 memcpy(buffer, &self->window[windowoffs], length); 0067 } 0068 else { 0069 /* Request wraps around window */ 0070 memcpy(buffer, &self->window[windowoffs], firstpart); 0071 memcpy(buffer + firstpart, &self->window[0], length - firstpart); 0072 } 0073 } 0074 0075 static inline bool lzss_initialize(LZSS *self, int windowsize) { 0076 self->window = malloc(windowsize); 0077 if (!self->window) 0078 return false; 0079 0080 self->mask = windowsize - 1; /* Assume windows are power-of-two sized! */ 0081 memset(self->window, 0, lzss_size(self)); 0082 self->position = 0; 0083 return true; 0084 } 0085 0086 static inline void lzss_cleanup(LZSS *self) { free(self->window); } 0087 0088 #endif