2 * @file circbuffer.h Buffer Utility Functions
6 /* Purple is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include "circbuffer.h"
28 #define DEFAULT_BUF_SIZE 256
31 purple_circ_buffer_new(gsize growsize
) {
32 PurpleCircBuffer
*buf
= g_new0(PurpleCircBuffer
, 1);
33 buf
->growsize
= growsize
? growsize
: DEFAULT_BUF_SIZE
;
37 void purple_circ_buffer_destroy(PurpleCircBuffer
*buf
) {
38 g_return_if_fail(buf
!= NULL
);
44 static void grow_circ_buffer(PurpleCircBuffer
*buf
, gsize len
) {
45 int in_offset
= 0, out_offset
= 0;
48 g_return_if_fail(buf
!= NULL
);
50 start_buflen
= buf
->buflen
;
52 while ((buf
->buflen
- buf
->bufused
) < len
)
53 buf
->buflen
+= buf
->growsize
;
55 if (buf
->inptr
!= NULL
) {
56 in_offset
= buf
->inptr
- buf
->buffer
;
57 out_offset
= buf
->outptr
- buf
->buffer
;
59 buf
->buffer
= g_realloc(buf
->buffer
, buf
->buflen
);
61 /* adjust the fill and remove pointer locations */
62 if (buf
->inptr
== NULL
) {
63 buf
->inptr
= buf
->outptr
= buf
->buffer
;
65 buf
->inptr
= buf
->buffer
+ in_offset
;
66 buf
->outptr
= buf
->buffer
+ out_offset
;
69 /* If the fill pointer is wrapped to before the remove
70 * pointer, we need to shift the data */
71 if (in_offset
< out_offset
72 || (in_offset
== out_offset
&& buf
->bufused
> 0)) {
73 int shift_n
= MIN(buf
->buflen
- start_buflen
,
75 memcpy(buf
->buffer
+ start_buflen
, buf
->buffer
,
78 /* If we couldn't fit the wrapped read buffer
80 if (shift_n
< in_offset
) {
82 buf
->buffer
+ shift_n
,
84 buf
->inptr
= buf
->buffer
+
85 (in_offset
- shift_n
);
87 buf
->inptr
= buf
->buffer
+
88 start_buflen
+ in_offset
;
93 void purple_circ_buffer_append(PurpleCircBuffer
*buf
, gconstpointer src
, gsize len
) {
97 g_return_if_fail(buf
!= NULL
);
99 /* Grow the buffer, if necessary */
100 if ((buf
->buflen
- buf
->bufused
) < len
)
101 grow_circ_buffer(buf
, len
);
103 /* If there is not enough room to copy all of src before hitting
104 * the end of the buffer then we will need to do two copies.
105 * One copy from inptr to the end of the buffer, and the
106 * second copy from the start of the buffer to the end of src. */
107 if (buf
->inptr
>= buf
->outptr
)
108 len_stored
= MIN(len
, buf
->buflen
109 - (buf
->inptr
- buf
->buffer
));
114 memcpy(buf
->inptr
, src
, len_stored
);
116 if (len_stored
< len
) {
117 memcpy(buf
->buffer
, (char*)src
+ len_stored
, len
- len_stored
);
118 buf
->inptr
= buf
->buffer
+ (len
- len_stored
);
120 buf
->inptr
+= len_stored
;
126 gsize
purple_circ_buffer_get_max_read(const PurpleCircBuffer
*buf
) {
129 g_return_val_if_fail(buf
!= NULL
, 0);
131 if (buf
->bufused
== 0)
133 else if ((buf
->outptr
- buf
->inptr
) >= 0)
134 max_read
= buf
->buflen
- (buf
->outptr
- buf
->buffer
);
136 max_read
= buf
->inptr
- buf
->outptr
;
141 gboolean
purple_circ_buffer_mark_read(PurpleCircBuffer
*buf
, gsize len
) {
142 g_return_val_if_fail(buf
!= NULL
, FALSE
);
143 g_return_val_if_fail(purple_circ_buffer_get_max_read(buf
) >= len
, FALSE
);
147 /* wrap to the start if we're at the end */
148 if ((buf
->outptr
- buf
->buffer
) == buf
->buflen
)
149 buf
->outptr
= buf
->buffer
;