comparison mcabber/src/hbuf.c @ 1364:ff1f6facdc0c

Allow dynamic HBB sizes
author Mikael Berthe <mikael@lilotux.net>
date Sun, 11 Nov 2007 23:13:35 +0100
parents e42f48103609
children 366ef500c522
comparison
equal deleted inserted replaced
1363:32077249de77 1364:ff1f6facdc0c
121 guint prefix_flags, guint width, guint maxhbufblocks, 121 guint prefix_flags, guint width, guint maxhbufblocks,
122 unsigned mucnicklen) 122 unsigned mucnicklen)
123 { 123 {
124 GList *curr_elt; 124 GList *curr_elt;
125 char *line; 125 char *line;
126 guint hbb_blocksize, textlen;
126 hbuf_block *hbuf_block_elt; 127 hbuf_block *hbuf_block_elt;
127 128
128 if (!text) return; 129 if (!text) return;
130
131 textlen = strlen(text);
132 hbb_blocksize = MAX(textlen+1, HBB_BLOCKSIZE);
129 133
130 hbuf_block_elt = g_new0(hbuf_block, 1); 134 hbuf_block_elt = g_new0(hbuf_block, 1);
131 hbuf_block_elt->prefix.timestamp = timestamp; 135 hbuf_block_elt->prefix.timestamp = timestamp;
132 hbuf_block_elt->prefix.flags = prefix_flags; 136 hbuf_block_elt->prefix.flags = prefix_flags;
133 hbuf_block_elt->prefix.mucnicklen = mucnicklen; 137 hbuf_block_elt->prefix.mucnicklen = mucnicklen;
134 if (!*p_hbuf) { 138 if (!*p_hbuf) {
135 hbuf_block_elt->ptr = g_new(char, HBB_BLOCKSIZE); 139 hbuf_block_elt->ptr = g_new(char, hbb_blocksize);
140 if (!hbuf_block_elt->ptr) {
141 g_free(hbuf_block_elt);
142 return;
143 }
136 hbuf_block_elt->flags = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT; 144 hbuf_block_elt->flags = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
137 hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE; 145 hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
138 } else { 146 } else {
139 hbuf_block *hbuf_b_prev; 147 hbuf_block *hbuf_b_prev;
140 // Set p_hbuf to the end of the list, to speed up history loading 148 // Set p_hbuf to the end of the list, to speed up history loading
141 // (or CPU time will be used by g_list_last() for each line) 149 // (or CPU time will be used by g_list_last() for each line)
142 *p_hbuf = g_list_last(*p_hbuf); 150 *p_hbuf = g_list_last(*p_hbuf);
145 hbuf_block_elt->flags = HBB_FLAG_PERSISTENT; 153 hbuf_block_elt->flags = HBB_FLAG_PERSISTENT;
146 hbuf_block_elt->ptr_end_alloc = hbuf_b_prev->ptr_end_alloc; 154 hbuf_block_elt->ptr_end_alloc = hbuf_b_prev->ptr_end_alloc;
147 } 155 }
148 *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt); 156 *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
149 157
150 if (strlen(text) >= HBB_BLOCKSIZE) { 158 if (hbuf_block_elt->ptr + textlen >= hbuf_block_elt->ptr_end_alloc) {
151 // Too long
152 text = "[ERR:LINE_TOO_LONG]";
153 hbuf_block_elt->prefix.flags |= HBB_PREFIX_INFO;
154 }
155
156 if (hbuf_block_elt->ptr + strlen(text) >= hbuf_block_elt->ptr_end_alloc) {
157 // Too long for the current allocated bloc, we need another one 159 // Too long for the current allocated bloc, we need another one
158 if (!maxhbufblocks) { 160 if (!maxhbufblocks || textlen >= HBB_BLOCKSIZE) {
159 // No limit, let's allocate a new block 161 // No limit, let's allocate a new block
160 hbuf_block_elt->ptr = g_new0(char, HBB_BLOCKSIZE); 162 // If the message text is big, we won't bother to reuse an old block
163 // as well (it could be too small and cause a segfault).
164 hbuf_block_elt->ptr = g_new0(char, hbb_blocksize);
165 hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
166 // XXX We should check the return value.
161 } else { 167 } else {
162 GList *hbuf_head, *hbuf_elt; 168 GList *hbuf_head, *hbuf_elt;
163 hbuf_block *hbuf_b_elt; 169 hbuf_block *hbuf_b_elt;
164 guint n = 0; 170 guint n = 0;
165 hbuf_head = g_list_first(*p_hbuf); 171 hbuf_head = g_list_first(*p_hbuf);
172 if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) 178 if (hbuf_b_elt->flags & HBB_FLAG_ALLOC)
173 n++; 179 n++;
174 } 180 }
175 // If we can't allocate a new area, reuse the previous block(s) 181 // If we can't allocate a new area, reuse the previous block(s)
176 if (n < maxhbufblocks) { 182 if (n < maxhbufblocks) {
177 hbuf_block_elt->ptr = g_new0(char, HBB_BLOCKSIZE); 183 hbuf_block_elt->ptr = g_new0(char, hbb_blocksize);
184 hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
178 } else { 185 } else {
179 // Let's use an old block, and free the extra blocks if needed 186 // Let's use an old block, and free the extra blocks if needed
180 char *allocated_block = NULL; 187 char *allocated_block = NULL;
188 char *end_of_allocated_block = NULL;
181 while (n >= maxhbufblocks) { 189 while (n >= maxhbufblocks) {
182 int start_of_block = 1; 190 int start_of_block = 1;
183 for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = hbuf_head) { 191 for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = hbuf_head) {
184 hbuf_b_elt = (hbuf_block*)(hbuf_elt->data); 192 hbuf_b_elt = (hbuf_block*)(hbuf_elt->data);
185 if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) { 193 if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
186 if (start_of_block-- == 0) 194 if (start_of_block-- == 0)
187 break; 195 break;
188 if (n == maxhbufblocks) 196 if (n == maxhbufblocks) {
189 allocated_block = hbuf_b_elt->ptr; 197 allocated_block = hbuf_b_elt->ptr;
190 else 198 end_of_allocated_block = hbuf_b_elt->ptr_end_alloc;
199 } else {
191 g_free(hbuf_b_elt->ptr); 200 g_free(hbuf_b_elt->ptr);
201 }
192 } 202 }
193 g_free(hbuf_b_elt); 203 g_free(hbuf_b_elt);
194 hbuf_head = *p_hbuf = g_list_delete_link(hbuf_head, hbuf_elt); 204 hbuf_head = *p_hbuf = g_list_delete_link(hbuf_head, hbuf_elt);
195 } 205 }
196 n--; 206 n--;
197 } 207 }
198 memset(allocated_block, 0, HBB_BLOCKSIZE); 208 memset(allocated_block, 0, end_of_allocated_block-allocated_block);
199 hbuf_block_elt->ptr = allocated_block; 209 hbuf_block_elt->ptr = allocated_block;
210 hbuf_block_elt->ptr_end_alloc = end_of_allocated_block;
200 } 211 }
201 } 212 }
202 hbuf_block_elt->flags = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT; 213 hbuf_block_elt->flags = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
203 hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
204 } 214 }
205 215
206 line = hbuf_block_elt->ptr; 216 line = hbuf_block_elt->ptr;
207 // Ok, now we can copy the text.. 217 // Ok, now we can copy the text..
208 strcpy(line, text); 218 strcpy(line, text);
209 hbuf_block_elt->ptr_end = line + strlen(line) + 1; 219 hbuf_block_elt->ptr_end = line + textlen + 1;
210 220
211 curr_elt = g_list_last(*p_hbuf); 221 curr_elt = g_list_last(*p_hbuf);
212 222
213 // Wrap lines and handle CRs ('\n') 223 // Wrap lines and handle CRs ('\n')
214 do_wrap(p_hbuf, curr_elt, width); 224 do_wrap(p_hbuf, curr_elt, width);