]>
Commit | Line | Data |
---|---|---|
31bfa062 CF |
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 | ||
c7179009 | 25 | #include "printfrr.h" |
31bfa062 CF |
26 | #include "sbuf.h" |
27 | #include "memory.h" | |
28 | ||
29 | void sbuf_init(struct sbuf *dest, char *buf, size_t size) | |
30 | { | |
31 | dest->fixed = (size > 0); | |
32 | if (dest->fixed) { | |
33 | dest->buf = buf; | |
34 | dest->size = size; | |
35 | } else { | |
36 | dest->buf = XMALLOC(MTYPE_TMP, 4096); | |
37 | dest->size = 4096; | |
38 | } | |
39 | ||
40 | dest->pos = 0; | |
41 | dest->buf[0] = '\0'; | |
42 | } | |
43 | ||
44 | void sbuf_reset(struct sbuf *dest) | |
45 | { | |
46 | dest->pos = 0; | |
47 | dest->buf[0] = '\0'; | |
48 | } | |
49 | ||
50 | const char *sbuf_buf(struct sbuf *buf) | |
51 | { | |
52 | return buf->buf; | |
53 | } | |
54 | ||
55 | void sbuf_free(struct sbuf *buf) | |
56 | { | |
57 | if (!buf->fixed) | |
58 | XFREE(MTYPE_TMP, buf->buf); | |
59 | } | |
60 | ||
61 | void sbuf_push(struct sbuf *buf, int indent, const char *format, ...) | |
62 | { | |
63 | va_list args; | |
64 | int written; | |
65 | ||
66 | if (!buf->fixed) { | |
31bfa062 CF |
67 | int written1, written2; |
68 | size_t new_size; | |
69 | ||
764f689b | 70 | written1 = indent; |
31bfa062 | 71 | va_start(args, format); |
c7179009 | 72 | written2 = vsnprintfrr(NULL, 0, format, args); |
31bfa062 CF |
73 | va_end(args); |
74 | ||
75 | new_size = buf->size; | |
76 | if (written1 >= 0 && written2 >= 0) { | |
77 | while (buf->pos + written1 + written2 >= new_size) | |
78 | new_size *= 2; | |
79 | if (new_size > buf->size) { | |
80 | buf->buf = | |
81 | XREALLOC(MTYPE_TMP, buf->buf, new_size); | |
82 | buf->size = new_size; | |
83 | } | |
84 | } | |
85 | } | |
86 | ||
87 | written = snprintf(buf->buf + buf->pos, buf->size - buf->pos, "%*s", | |
88 | indent, ""); | |
89 | ||
90 | if (written >= 0) | |
91 | buf->pos += written; | |
92 | if (buf->pos > buf->size) | |
93 | buf->pos = buf->size; | |
94 | ||
95 | va_start(args, format); | |
c7179009 DL |
96 | written = vsnprintfrr(buf->buf + buf->pos, buf->size - buf->pos, |
97 | format, args); | |
31bfa062 CF |
98 | va_end(args); |
99 | ||
100 | if (written >= 0) | |
101 | buf->pos += written; | |
102 | if (buf->pos > buf->size) | |
103 | buf->pos = buf->size; | |
104 | ||
105 | if (buf->pos == buf->size) | |
106 | assert(!"Buffer filled up!"); | |
107 | } |