Line data Source code
1 : /*
2 : * Simple string buffer
3 : *
4 : * Copyright (C) 2017 Christian Franke
5 : *
6 : * This file is part of FRR.
7 : *
8 : * FRR is free software; you can redistribute it and/or modify it
9 : * under the terms of the GNU General Public License as published by the
10 : * Free Software Foundation; either version 2, or (at your option) any
11 : * later version.
12 : *
13 : * FRR is distributed in the hope that it will be useful, but
14 : * WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : * General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with FRR; see the file COPYING. If not, write to the Free
20 : * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 : * 02111-1307, USA.
22 : */
23 : #include <zebra.h>
24 :
25 : #include "printfrr.h"
26 : #include "sbuf.h"
27 : #include "memory.h"
28 :
29 0 : void sbuf_init(struct sbuf *dest, char *buf, size_t size)
30 : {
31 0 : dest->fixed = (size > 0);
32 0 : if (dest->fixed) {
33 0 : dest->buf = buf;
34 0 : dest->size = size;
35 : } else {
36 0 : dest->buf = XMALLOC(MTYPE_TMP, 4096);
37 0 : dest->size = 4096;
38 : }
39 :
40 0 : dest->pos = 0;
41 0 : dest->buf[0] = '\0';
42 0 : }
43 :
44 0 : void sbuf_reset(struct sbuf *dest)
45 : {
46 0 : dest->pos = 0;
47 0 : dest->buf[0] = '\0';
48 0 : }
49 :
50 0 : const char *sbuf_buf(struct sbuf *buf)
51 : {
52 0 : return buf->buf;
53 : }
54 :
55 0 : void sbuf_free(struct sbuf *buf)
56 : {
57 0 : if (!buf->fixed)
58 0 : XFREE(MTYPE_TMP, buf->buf);
59 0 : }
60 :
61 0 : void sbuf_push(struct sbuf *buf, int indent, const char *format, ...)
62 : {
63 0 : va_list args;
64 0 : int written;
65 :
66 0 : if (!buf->fixed) {
67 0 : int written1, written2;
68 0 : size_t new_size;
69 :
70 0 : written1 = indent;
71 0 : va_start(args, format);
72 0 : written2 = vsnprintfrr(NULL, 0, format, args);
73 0 : va_end(args);
74 :
75 0 : new_size = buf->size;
76 0 : if (written1 >= 0 && written2 >= 0) {
77 0 : while (buf->pos + written1 + written2 >= new_size)
78 0 : new_size *= 2;
79 0 : if (new_size > buf->size) {
80 0 : buf->buf =
81 0 : XREALLOC(MTYPE_TMP, buf->buf, new_size);
82 0 : buf->size = new_size;
83 : }
84 : }
85 : }
86 :
87 0 : written = snprintf(buf->buf + buf->pos, buf->size - buf->pos, "%*s",
88 : indent, "");
89 :
90 0 : if (written >= 0)
91 0 : buf->pos += written;
92 0 : if (buf->pos > buf->size)
93 0 : buf->pos = buf->size;
94 :
95 0 : va_start(args, format);
96 0 : written = vsnprintfrr(buf->buf + buf->pos, buf->size - buf->pos,
97 : format, args);
98 0 : va_end(args);
99 :
100 0 : if (written >= 0)
101 0 : buf->pos += written;
102 0 : if (buf->pos > buf->size)
103 0 : buf->pos = buf->size;
104 :
105 0 : if (buf->pos == buf->size)
106 0 : assert(!"Buffer filled up!");
107 0 : }
|