OLD | NEW |
(Empty) | |
| 1 /////////////////////////////////////////////////////////////////////////////// |
| 2 // |
| 3 /// \file common.h |
| 4 /// \brief Common functions needed in many places in liblzma |
| 5 // |
| 6 // Author: Lasse Collin |
| 7 // |
| 8 // This file has been put into the public domain. |
| 9 // You can do whatever you want with this file. |
| 10 // |
| 11 /////////////////////////////////////////////////////////////////////////////// |
| 12 |
| 13 #include "common.h" |
| 14 |
| 15 |
| 16 ///////////// |
| 17 // Version // |
| 18 ///////////// |
| 19 |
| 20 extern LZMA_API(uint32_t) |
| 21 lzma_version_number(void) |
| 22 { |
| 23 return LZMA_VERSION; |
| 24 } |
| 25 |
| 26 |
| 27 extern LZMA_API(const char *) |
| 28 lzma_version_string(void) |
| 29 { |
| 30 return LZMA_VERSION_STRING; |
| 31 } |
| 32 |
| 33 |
| 34 /////////////////////// |
| 35 // Memory allocation // |
| 36 /////////////////////// |
| 37 |
| 38 extern void * lzma_attribute((malloc)) |
| 39 lzma_alloc(size_t size, lzma_allocator *allocator) |
| 40 { |
| 41 // Some malloc() variants return NULL if called with size == 0. |
| 42 if (size == 0) |
| 43 size = 1; |
| 44 |
| 45 void *ptr; |
| 46 |
| 47 if (allocator != NULL && allocator->alloc != NULL) |
| 48 ptr = allocator->alloc(allocator->opaque, 1, size); |
| 49 else |
| 50 ptr = malloc(size); |
| 51 |
| 52 return ptr; |
| 53 } |
| 54 |
| 55 |
| 56 extern void |
| 57 lzma_free(void *ptr, lzma_allocator *allocator) |
| 58 { |
| 59 if (allocator != NULL && allocator->free != NULL) |
| 60 allocator->free(allocator->opaque, ptr); |
| 61 else |
| 62 free(ptr); |
| 63 |
| 64 return; |
| 65 } |
| 66 |
| 67 |
| 68 ////////// |
| 69 // Misc // |
| 70 ////////// |
| 71 |
| 72 extern size_t |
| 73 lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, |
| 74 size_t in_size, uint8_t *restrict out, |
| 75 size_t *restrict out_pos, size_t out_size) |
| 76 { |
| 77 const size_t in_avail = in_size - *in_pos; |
| 78 const size_t out_avail = out_size - *out_pos; |
| 79 const size_t copy_size = my_min(in_avail, out_avail); |
| 80 |
| 81 memcpy(out + *out_pos, in + *in_pos, copy_size); |
| 82 |
| 83 *in_pos += copy_size; |
| 84 *out_pos += copy_size; |
| 85 |
| 86 return copy_size; |
| 87 } |
| 88 |
| 89 |
| 90 extern lzma_ret |
| 91 lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator, |
| 92 const lzma_filter_info *filters) |
| 93 { |
| 94 lzma_next_coder_init(filters[0].init, next, allocator); |
| 95 next->id = filters[0].id; |
| 96 return filters[0].init == NULL |
| 97 ? LZMA_OK : filters[0].init(next, allocator, filters); |
| 98 } |
| 99 |
| 100 |
| 101 extern lzma_ret |
| 102 lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator, |
| 103 const lzma_filter *reversed_filters) |
| 104 { |
| 105 // Check that the application isn't trying to change the Filter ID. |
| 106 // End of filters is indicated with LZMA_VLI_UNKNOWN in both |
| 107 // reversed_filters[0].id and next->id. |
| 108 if (reversed_filters[0].id != next->id) |
| 109 return LZMA_PROG_ERROR; |
| 110 |
| 111 if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) |
| 112 return LZMA_OK; |
| 113 |
| 114 assert(next->update != NULL); |
| 115 return next->update(next->coder, allocator, NULL, reversed_filters); |
| 116 } |
| 117 |
| 118 |
| 119 extern void |
| 120 lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator) |
| 121 { |
| 122 if (next->init != (uintptr_t)(NULL)) { |
| 123 // To avoid tiny end functions that simply call |
| 124 // lzma_free(coder, allocator), we allow leaving next->end |
| 125 // NULL and call lzma_free() here. |
| 126 if (next->end != NULL) |
| 127 next->end(next->coder, allocator); |
| 128 else |
| 129 lzma_free(next->coder, allocator); |
| 130 |
| 131 // Reset the variables so the we don't accidentally think |
| 132 // that it is an already initialized coder. |
| 133 *next = LZMA_NEXT_CODER_INIT; |
| 134 } |
| 135 |
| 136 return; |
| 137 } |
| 138 |
| 139 |
| 140 ////////////////////////////////////// |
| 141 // External to internal API wrapper // |
| 142 ////////////////////////////////////// |
| 143 |
| 144 extern lzma_ret |
| 145 lzma_strm_init(lzma_stream *strm) |
| 146 { |
| 147 if (strm == NULL) |
| 148 return LZMA_PROG_ERROR; |
| 149 |
| 150 if (strm->internal == NULL) { |
| 151 strm->internal = lzma_alloc(sizeof(lzma_internal), |
| 152 strm->allocator); |
| 153 if (strm->internal == NULL) |
| 154 return LZMA_MEM_ERROR; |
| 155 |
| 156 strm->internal->next = LZMA_NEXT_CODER_INIT; |
| 157 } |
| 158 |
| 159 strm->internal->supported_actions[LZMA_RUN] = false; |
| 160 strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false; |
| 161 strm->internal->supported_actions[LZMA_FULL_FLUSH] = false; |
| 162 strm->internal->supported_actions[LZMA_FINISH] = false; |
| 163 strm->internal->sequence = ISEQ_RUN; |
| 164 strm->internal->allow_buf_error = false; |
| 165 |
| 166 strm->total_in = 0; |
| 167 strm->total_out = 0; |
| 168 |
| 169 return LZMA_OK; |
| 170 } |
| 171 |
| 172 |
| 173 extern LZMA_API(lzma_ret) |
| 174 lzma_code(lzma_stream *strm, lzma_action action) |
| 175 { |
| 176 // Sanity checks |
| 177 if ((strm->next_in == NULL && strm->avail_in != 0) |
| 178 || (strm->next_out == NULL && strm->avail_out != 0) |
| 179 || strm->internal == NULL |
| 180 || strm->internal->next.code == NULL |
| 181 || (unsigned int)(action) > LZMA_FINISH |
| 182 || !strm->internal->supported_actions[action]) |
| 183 return LZMA_PROG_ERROR; |
| 184 |
| 185 switch (strm->internal->sequence) { |
| 186 case ISEQ_RUN: |
| 187 switch (action) { |
| 188 case LZMA_RUN: |
| 189 break; |
| 190 |
| 191 case LZMA_SYNC_FLUSH: |
| 192 strm->internal->sequence = ISEQ_SYNC_FLUSH; |
| 193 break; |
| 194 |
| 195 case LZMA_FULL_FLUSH: |
| 196 strm->internal->sequence = ISEQ_FULL_FLUSH; |
| 197 break; |
| 198 |
| 199 case LZMA_FINISH: |
| 200 strm->internal->sequence = ISEQ_FINISH; |
| 201 break; |
| 202 } |
| 203 |
| 204 break; |
| 205 |
| 206 case ISEQ_SYNC_FLUSH: |
| 207 // The same action must be used until we return |
| 208 // LZMA_STREAM_END, and the amount of input must not change. |
| 209 if (action != LZMA_SYNC_FLUSH |
| 210 || strm->internal->avail_in != strm->avail_in) |
| 211 return LZMA_PROG_ERROR; |
| 212 |
| 213 break; |
| 214 |
| 215 case ISEQ_FULL_FLUSH: |
| 216 if (action != LZMA_FULL_FLUSH |
| 217 || strm->internal->avail_in != strm->avail_in) |
| 218 return LZMA_PROG_ERROR; |
| 219 |
| 220 break; |
| 221 |
| 222 case ISEQ_FINISH: |
| 223 if (action != LZMA_FINISH |
| 224 || strm->internal->avail_in != strm->avail_in) |
| 225 return LZMA_PROG_ERROR; |
| 226 |
| 227 break; |
| 228 |
| 229 case ISEQ_END: |
| 230 return LZMA_STREAM_END; |
| 231 |
| 232 case ISEQ_ERROR: |
| 233 default: |
| 234 return LZMA_PROG_ERROR; |
| 235 } |
| 236 |
| 237 size_t in_pos = 0; |
| 238 size_t out_pos = 0; |
| 239 lzma_ret ret = strm->internal->next.code( |
| 240 strm->internal->next.coder, strm->allocator, |
| 241 strm->next_in, &in_pos, strm->avail_in, |
| 242 strm->next_out, &out_pos, strm->avail_out, action); |
| 243 |
| 244 strm->next_in += in_pos; |
| 245 strm->avail_in -= in_pos; |
| 246 strm->total_in += in_pos; |
| 247 |
| 248 strm->next_out += out_pos; |
| 249 strm->avail_out -= out_pos; |
| 250 strm->total_out += out_pos; |
| 251 |
| 252 strm->internal->avail_in = strm->avail_in; |
| 253 |
| 254 switch (ret) { |
| 255 case LZMA_OK: |
| 256 // Don't return LZMA_BUF_ERROR when it happens the first time. |
| 257 // This is to avoid returning LZMA_BUF_ERROR when avail_out |
| 258 // was zero but still there was no more data left to written |
| 259 // to next_out. |
| 260 if (out_pos == 0 && in_pos == 0) { |
| 261 if (strm->internal->allow_buf_error) |
| 262 ret = LZMA_BUF_ERROR; |
| 263 else |
| 264 strm->internal->allow_buf_error = true; |
| 265 } else { |
| 266 strm->internal->allow_buf_error = false; |
| 267 } |
| 268 break; |
| 269 |
| 270 case LZMA_STREAM_END: |
| 271 if (strm->internal->sequence == ISEQ_SYNC_FLUSH |
| 272 || strm->internal->sequence == ISEQ_FULL_FLUSH) |
| 273 strm->internal->sequence = ISEQ_RUN; |
| 274 else |
| 275 strm->internal->sequence = ISEQ_END; |
| 276 |
| 277 // Fall through |
| 278 |
| 279 case LZMA_NO_CHECK: |
| 280 case LZMA_UNSUPPORTED_CHECK: |
| 281 case LZMA_GET_CHECK: |
| 282 case LZMA_MEMLIMIT_ERROR: |
| 283 // Something else than LZMA_OK, but not a fatal error, |
| 284 // that is, coding may be continued (except if ISEQ_END). |
| 285 strm->internal->allow_buf_error = false; |
| 286 break; |
| 287 |
| 288 default: |
| 289 // All the other errors are fatal; coding cannot be continued. |
| 290 assert(ret != LZMA_BUF_ERROR); |
| 291 strm->internal->sequence = ISEQ_ERROR; |
| 292 break; |
| 293 } |
| 294 |
| 295 return ret; |
| 296 } |
| 297 |
| 298 |
| 299 extern LZMA_API(void) |
| 300 lzma_end(lzma_stream *strm) |
| 301 { |
| 302 if (strm != NULL && strm->internal != NULL) { |
| 303 lzma_next_end(&strm->internal->next, strm->allocator); |
| 304 lzma_free(strm->internal, strm->allocator); |
| 305 strm->internal = NULL; |
| 306 } |
| 307 |
| 308 return; |
| 309 } |
| 310 |
| 311 |
| 312 extern LZMA_API(lzma_check) |
| 313 lzma_get_check(const lzma_stream *strm) |
| 314 { |
| 315 // Return LZMA_CHECK_NONE if we cannot know the check type. |
| 316 // It's a bug in the application if this happens. |
| 317 if (strm->internal->next.get_check == NULL) |
| 318 return LZMA_CHECK_NONE; |
| 319 |
| 320 return strm->internal->next.get_check(strm->internal->next.coder); |
| 321 } |
| 322 |
| 323 |
| 324 extern LZMA_API(uint64_t) |
| 325 lzma_memusage(const lzma_stream *strm) |
| 326 { |
| 327 uint64_t memusage; |
| 328 uint64_t old_memlimit; |
| 329 |
| 330 if (strm == NULL || strm->internal == NULL |
| 331 || strm->internal->next.memconfig == NULL |
| 332 || strm->internal->next.memconfig( |
| 333 strm->internal->next.coder, |
| 334 &memusage, &old_memlimit, 0) != LZMA_OK) |
| 335 return 0; |
| 336 |
| 337 return memusage; |
| 338 } |
| 339 |
| 340 |
| 341 extern LZMA_API(uint64_t) |
| 342 lzma_memlimit_get(const lzma_stream *strm) |
| 343 { |
| 344 uint64_t old_memlimit; |
| 345 uint64_t memusage; |
| 346 |
| 347 if (strm == NULL || strm->internal == NULL |
| 348 || strm->internal->next.memconfig == NULL |
| 349 || strm->internal->next.memconfig( |
| 350 strm->internal->next.coder, |
| 351 &memusage, &old_memlimit, 0) != LZMA_OK) |
| 352 return 0; |
| 353 |
| 354 return old_memlimit; |
| 355 } |
| 356 |
| 357 |
| 358 extern LZMA_API(lzma_ret) |
| 359 lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) |
| 360 { |
| 361 // Dummy variables to simplify memconfig functions |
| 362 uint64_t old_memlimit; |
| 363 uint64_t memusage; |
| 364 |
| 365 if (strm == NULL || strm->internal == NULL |
| 366 || strm->internal->next.memconfig == NULL) |
| 367 return LZMA_PROG_ERROR; |
| 368 |
| 369 if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE) |
| 370 return LZMA_MEMLIMIT_ERROR; |
| 371 |
| 372 return strm->internal->next.memconfig(strm->internal->next.coder, |
| 373 &memusage, &old_memlimit, new_memlimit); |
| 374 } |
OLD | NEW |