/src/htslib/cram/string_alloc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2010, 2013, 2018-2019 Genome Research Ltd. |
3 | | Author: Andrew Whitwham <aw7@sanger.ac.uk> |
4 | | |
5 | | Redistribution and use in source and binary forms, with or without |
6 | | modification, are permitted provided that the following conditions are met: |
7 | | |
8 | | 1. Redistributions of source code must retain the above copyright notice, |
9 | | this list of conditions and the following disclaimer. |
10 | | |
11 | | 2. Redistributions in binary form must reproduce the above copyright notice, |
12 | | this list of conditions and the following disclaimer in the documentation |
13 | | and/or other materials provided with the distribution. |
14 | | |
15 | | 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger |
16 | | Institute nor the names of its contributors may be used to endorse or promote |
17 | | products derived from this software without specific prior written permission. |
18 | | |
19 | | THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND |
20 | | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
21 | | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | | DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE |
23 | | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
25 | | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
26 | | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
27 | | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | | */ |
30 | | |
31 | | |
32 | | /* |
33 | | A pooled string allocator intended to cut down on the |
34 | | memory overhead of many small string allocations. |
35 | | |
36 | | Andrew Whitwham, September 2010. |
37 | | */ |
38 | | |
39 | | #define HTS_BUILDING_LIBRARY // Enables HTSLIB_EXPORT, see htslib/hts_defs.h |
40 | | #include <config.h> |
41 | | |
42 | | #include <string.h> |
43 | | #include <stdlib.h> |
44 | | #include <stdio.h> |
45 | | |
46 | | #include "string_alloc.h" |
47 | | |
48 | 2.15k | #define MIN_STR_SIZE 1024 |
49 | | |
50 | | |
51 | | /* creates the string pool. max_length is the initial size |
52 | | a single string can be. The max_length can grow as |
53 | | needed */ |
54 | | |
55 | 2.15k | string_alloc_t *string_pool_create(size_t max_length) { |
56 | 2.15k | string_alloc_t *a_str; |
57 | | |
58 | 2.15k | if (NULL == (a_str = (string_alloc_t *)malloc(sizeof(*a_str)))) { |
59 | 0 | return NULL; |
60 | 0 | } |
61 | | |
62 | 2.15k | if (max_length < MIN_STR_SIZE) max_length = MIN_STR_SIZE; |
63 | | |
64 | 2.15k | a_str->nstrings = 0; |
65 | 2.15k | a_str->max_strings = 0; |
66 | 2.15k | a_str->max_length = max_length; |
67 | 2.15k | a_str->strings = NULL; |
68 | | |
69 | 2.15k | return a_str; |
70 | 2.15k | } |
71 | | |
72 | | |
73 | | /* internal function to do the actual memory allocation */ |
74 | | |
75 | 3.20k | static string_t *new_string_pool(string_alloc_t *a_str) { |
76 | 3.20k | string_t *str; |
77 | | |
78 | 3.20k | if (a_str->nstrings == a_str->max_strings) { |
79 | 1.83k | size_t new_max = (a_str->max_strings | (a_str->max_strings >> 2)) + 1; |
80 | 1.83k | str = realloc(a_str->strings, new_max * sizeof(*a_str->strings)); |
81 | | |
82 | 1.83k | if (NULL == str) return NULL; |
83 | | |
84 | 1.83k | a_str->strings = str; |
85 | 1.83k | a_str->max_strings = new_max; |
86 | 1.83k | } |
87 | | |
88 | 3.20k | str = &a_str->strings[a_str->nstrings]; |
89 | | |
90 | 3.20k | str->str = malloc(a_str->max_length); |
91 | | |
92 | 3.20k | if (NULL == str->str) return NULL; |
93 | | |
94 | 3.20k | str->used = 0; |
95 | 3.20k | a_str->nstrings++; |
96 | | |
97 | 3.20k | return str; |
98 | 3.20k | } |
99 | | |
100 | | |
101 | | /* free allocated memory */ |
102 | | |
103 | 2.15k | void string_pool_destroy(string_alloc_t *a_str) { |
104 | 2.15k | size_t i; |
105 | | |
106 | 5.36k | for (i = 0; i < a_str->nstrings; i++) { |
107 | 3.20k | free(a_str->strings[i].str); |
108 | 3.20k | } |
109 | | |
110 | 2.15k | free(a_str->strings); |
111 | 2.15k | free(a_str); |
112 | 2.15k | } |
113 | | |
114 | | |
115 | | /* allocate space for a string */ |
116 | | |
117 | 712k | char *string_alloc(string_alloc_t *a_str, size_t length) { |
118 | 712k | string_t *str; |
119 | 712k | char *ret; |
120 | | |
121 | 712k | if (length <= 0) return NULL; |
122 | | |
123 | | // add to last string pool if we have space |
124 | 712k | if (a_str->nstrings) { |
125 | 711k | str = &a_str->strings[a_str->nstrings - 1]; |
126 | | |
127 | 711k | if (str->used + length < a_str->max_length) { |
128 | 709k | ret = str->str + str->used; |
129 | 709k | str->used += length; |
130 | 709k | return ret; |
131 | 709k | } |
132 | 711k | } |
133 | | |
134 | | // increase the max length if needs be |
135 | 3.20k | if (length > a_str->max_length) a_str->max_length = length; |
136 | | |
137 | | // need a new string pool |
138 | 3.20k | str = new_string_pool(a_str); |
139 | | |
140 | 3.20k | if (NULL == str) return NULL; |
141 | | |
142 | 3.20k | str->used = length; |
143 | 3.20k | return str->str; |
144 | 3.20k | } |
145 | | |
146 | | |
147 | | /* equivalent to strdup */ |
148 | | |
149 | 8.21k | char *string_dup(string_alloc_t *a_str, const char *instr) { |
150 | 8.21k | return string_ndup(a_str, instr, strlen(instr)); |
151 | 8.21k | } |
152 | | |
153 | 707k | char *string_ndup(string_alloc_t *a_str, const char *instr, size_t len) { |
154 | 707k | char *str = string_alloc(a_str, len + 1); |
155 | | |
156 | 707k | if (NULL == str) return NULL; |
157 | | |
158 | 707k | memcpy(str, instr, len); |
159 | 707k | str[len] = 0; |
160 | | |
161 | 707k | return str; |
162 | 707k | } |