xref: /trafficserver/src/tscore/ink_string++.cc (revision 4cfd5a73)
1 /** @file
2 
3   A brief file description
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 /****************************************************************************
25 
26   ink_string++.cc
27 
28   C++ support for string manipulation.
29 
30 
31  ****************************************************************************/
32 
33 #include "tscore/ink_platform.h"
34 #include "tscore/ink_string++.h"
35 #include "tscore/ink_assert.h"
36 #include "tscore/ink_memory.h"
37 #include "tscore/ink_align.h"
38 
39 /***********************************************************************
40  *                                                                     *
41  *       StrList (doubly-linked list of string/length list cells)      *
42  *                                                                     *
43  ***********************************************************************/
44 
45 /*-------------------------------------------------------------------------
46   -------------------------------------------------------------------------*/
47 
48 void
dump(FILE * fp)49 StrList::dump(FILE *fp)
50 {
51   Str *str;
52 
53   for (str = head; str != nullptr; str = str->next) {
54     str->dump(fp);
55   }
56 }
57 
58 /*-------------------------------------------------------------------------
59   -------------------------------------------------------------------------*/
60 
61 Str *
_new_cell(const char * s,int len_not_counting_nul)62 StrList::_new_cell(const char *s, int len_not_counting_nul)
63 {
64   Str *cell;
65   char *p;
66   int l = len_not_counting_nul;
67 
68   // allocate a cell from the array or heap
69   if (cells_allocated < STRLIST_BASE_CELLS) {
70     cell = &(base_cells[cells_allocated]);
71   } else {
72     p = static_cast<char *>(alloc(sizeof(Str) + 7));
73     if (p == nullptr) {
74       return (nullptr); // FIX: scale heap
75     }
76     p    = (char *)((((uintptr_t)p) + 7) & ~7); // round up to multiple of 8
77     cell = reinterpret_cast<Str *>(p);
78   }
79   ++cells_allocated;
80 
81   // are we supposed to copy the string?
82   if (copy_when_adding_string) {
83     char *buf = static_cast<char *>(alloc(l + 1));
84     if (buf == nullptr) {
85       return (nullptr); // FIX: need to grow heap!
86     }
87     memcpy(buf, s, l);
88     buf[l] = '\0';
89 
90     cell->str = (const char *)buf;
91   } else {
92     cell->str = s;
93   }
94 
95   cell->len = l;
96 
97   return (cell);
98 }
99 
100 /*-------------------------------------------------------------------------
101   -------------------------------------------------------------------------*/
102 
103 void *
overflow_heap_alloc(int size)104 StrList::overflow_heap_alloc(int size)
105 {
106   if (!overflow_first) {
107     overflow_first = overflow_current = StrListOverflow::create_heap(STRLIST_OVERFLOW_HEAP_SIZE);
108   }
109 
110   return overflow_current->alloc(size, &overflow_current);
111 }
112 
113 /*-------------------------------------------------------------------------
114   -------------------------------------------------------------------------*/
115 
116 void
overflow_heap_clean()117 StrList::overflow_heap_clean()
118 {
119   if (overflow_first) {
120     overflow_first->clean();
121   }
122 }
123 
124 #define INIT_OVERFLOW_ALIGNMENT 8
125 // XXX: This is basically INK_ALIGN_DEFAULT
126 const int overflow_head_hdr_size = INK_ALIGN(sizeof(StrListOverflow), INIT_OVERFLOW_ALIGNMENT);
127 
128 void
init()129 StrListOverflow::init()
130 {
131   next      = nullptr;
132   heap_size = 0;
133   heap_used = 0;
134 }
135 
136 void
clean()137 StrListOverflow::clean()
138 {
139   StrListOverflow *current_free = this;
140   StrListOverflow *next_free;
141 
142   while (current_free) {
143     next_free = current_free->next;
144     ats_free(current_free);
145     current_free = next_free;
146   }
147 }
148 
149 void *
alloc(int size,StrListOverflow ** new_heap_ptr)150 StrListOverflow::alloc(int size, StrListOverflow **new_heap_ptr)
151 {
152   if (size > (heap_size - heap_used)) {
153     int new_heap_size = heap_size * 2;
154 
155     if (new_heap_size < size) {
156       new_heap_size = INK_ALIGN(size, 2048);
157       ink_release_assert(new_heap_size >= size);
158     }
159 
160     ink_assert(next == nullptr);
161     *new_heap_ptr = next = create_heap(new_heap_size);
162     return next->alloc(size, new_heap_ptr);
163   }
164 
165   char *start = (reinterpret_cast<char *>(this)) + overflow_head_hdr_size;
166   char *rval  = start + heap_used;
167   heap_used += size;
168   ink_assert(heap_used <= heap_size);
169   return (void *)rval;
170 }
171 
172 StrListOverflow *
create_heap(int user_size)173 StrListOverflow::create_heap(int user_size)
174 {
175   // I'm aligning the first allocation since the old implementation
176   //  used to do this by calling ats_malloc.  I assume it doesn't
177   //  matter since we are talking about strings but since this is a
178   //  last minute emergency bug fix, I'm not take any changes.  If
179   //  allocations are not of aligned values then subsequents allocations
180   //  aren't aligned, again mirroring the previous implementation
181   int total_size = overflow_head_hdr_size + user_size;
182 
183   StrListOverflow *o = static_cast<StrListOverflow *>(ats_malloc(total_size));
184   o->init();
185   o->heap_size = user_size;
186 
187   return o;
188 }
189