Squash  0.7.0
buffer.c
1 /* Copyright (c) 2013 The Squash Authors
2  *
3  * Permission is hereby granted, free of charge, to any person
4  * obtaining a copy of this software and associated documentation
5  * files (the "Software"), to deal in the Software without
6  * restriction, including without limitation the rights to use, copy,
7  * modify, merge, publish, distribute, sublicense, and/or sell copies
8  * of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  * Evan Nemerson <evan@nemerson.com>
25  */
26 
27 #include <squash/config.h>
28 
29 #if defined(HAVE_MMAP)
30 # define _POSIX_SOURCE
31 # define _GNU_SOURCE
32 # include <unistd.h>
33 # if defined(HAVE_MREMAP)
34 # include <sys/types.h>
35 # include <sys/mman.h>
36 #endif
37 #endif
38 
39 #include <assert.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include <stdio.h>
44 
45 #include "internal.h"
46 
47 static size_t
48 squash_buffer_npot_page (size_t value) {
49 #if defined(_POSIX_SOURCE)
50  static size_t page_size = 0;
51 
52  if (page_size == 0) {
53  long ps = sysconf (_SC_PAGE_SIZE);
54  page_size = (ps == -1) ? 8192 : ((size_t) ps);
55  }
56 
57  if (value < page_size)
58  value = page_size;
59 #else
60  if (value < 4096)
61  value = 4096;
62 #endif
63 
64  if ((value & (value - 1)) != 0) {
65  value -= 1;
66  value |= value >> 1;
67  value |= value >> 2;
68  value |= value >> 4;
69  value |= value >> 8;
70  value |= value >> 16;
71  value++;
72  }
73 
74  return value;
75 }
76 
77 static void
78 squash_buffer_ensure_allocation (SquashBuffer* buffer, size_t allocation) {
79  if (allocation > buffer->allocated) {
80  allocation = squash_buffer_npot_page (allocation);
81  buffer->allocated = allocation;
82  buffer->data = (uint8_t*) realloc (buffer->data, allocation);
83  }
84 }
85 
93 SquashBuffer*
94 squash_buffer_new (size_t preallocated_len) {
95  SquashBuffer* buffer = (SquashBuffer*) malloc (sizeof (SquashBuffer));
96 
97  buffer->data = preallocated_len > 0 ? (uint8_t*) malloc (preallocated_len) : NULL;
98  buffer->length = 0;
99  buffer->allocated = preallocated_len;
100 
101  return buffer;
102 }
103 
104 void
105 squash_buffer_set_size (SquashBuffer* buffer, size_t length) {
106  if (length > buffer->allocated)
107  squash_buffer_ensure_allocation (buffer, length);
108 
109  buffer->length = length;
110 }
111 
112 void
113 squash_buffer_clear (SquashBuffer* buffer) {
114  free (buffer->data);
115  buffer->data = NULL;
116  buffer->allocated = 0;
117  buffer->length = 0;
118 }
119 
120 void
121 squash_buffer_append (SquashBuffer* buffer, uint8_t* data, size_t data_length) {
122  const size_t start_pos = buffer->length;
123 
124  squash_buffer_set_size (buffer, buffer->length + data_length);
125 
126  memcpy (buffer->data + start_pos, data, data_length);
127 }
128 
129 void
130 squash_buffer_free (SquashBuffer* buffer) {
131  if (buffer->data != NULL) {
132  free (buffer->data);
133  }
134  free (buffer);
135 }