Mercurial > hg
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); |