1/***********************************************************************
2*
3* l2tp/handlers/dstring.c
4*
5* Implements simple buffer which grows to accomodate accumulated string
6* data
7*
8* Copyright (C) 2002 by Roaring Penguin Software Inc.
9*
10* This software may be distributed under the terms of the GNU General
11* Public License, Version 2, or (at your option) any later version.
12*
13* LIC: GPL
14*
15***********************************************************************/
16
17static char const RCSID[] =
18"$Id: dstring.c 3323 2011-09-21 18:45:48Z lly.dev $";
19
20#define INITIAL_SIZE 128
21#define GROW_FACTOR 2
22
23#include "dstring.h"
24#include <stdlib.h>
25#include <string.h>
26
27static int
28expand_for_size(dynstring *str, size_t len)
29{
30    size_t newlen;
31
32    if (len >= str->alloc_size * GROW_FACTOR) {
33	newlen = len + 1;
34    } else {
35	newlen = str->alloc_size * GROW_FACTOR;
36    }
37
38    str->data = realloc(str->data, newlen);
39    if (!str->data) {
40	str->alloc_size = 0;
41	str->actual_size = 0;
42	return -1;
43    }
44
45    str->alloc_size = newlen;
46    return 0;
47}
48
49/**********************************************************************
50* %FUNCTION: dynstring_init
51* %ARGUMENTS:
52*  str -- a dynstring structure
53* %RETURNS:
54*  0 on success; -1 on failure
55* %DESCRIPTION:
56*  Initializes dynamic string
57***********************************************************************/
58int
59dynstring_init(dynstring *str)
60{
61    str->data = malloc(INITIAL_SIZE);
62    if (!str->data) return -1;
63
64    str->alloc_size = INITIAL_SIZE;
65    str->actual_size = 0;
66    str->data[0] = 0;
67    return 0;
68}
69
70/**********************************************************************
71* %FUNCTION: dynstring_free
72* %ARGUMENTS:
73*  str -- a dynstring structure
74* %RETURNS:
75*  Nothing
76* %DESCRIPTION:
77*  Frees resources used by dynamic string
78***********************************************************************/
79void
80dynstring_free(dynstring *str)
81{
82    if (str->data) {
83	free(str->data);
84	str->data = NULL;
85    }
86    str->alloc_size = 0;
87    str->actual_size = 0;
88}
89
90/**********************************************************************
91* %FUNCTION: dynstring_append
92* %ARGUMENTS:
93*  str -- dynamic string
94*  s2 -- string to append
95* %RETURNS:
96*  -1 on failure; 0 on success
97* %DESCRIPTION:
98*  Appends s2 to str
99***********************************************************************/
100int
101dynstring_append(dynstring *str, char const *s2)
102{
103    return dynstring_append_len(str, s2, strlen(s2));
104}
105
106/**********************************************************************
107* %FUNCTION: dynstring_append_len
108* %ARGUMENTS:
109*  str -- dynamic string
110*  s2 -- string to append
111*  len -- length of s2
112* %RETURNS:
113*  -1 on failure; 0 on success
114* %DESCRIPTION:
115*  Appends s2 to str
116***********************************************************************/
117int
118dynstring_append_len(dynstring *str, char const *s2, size_t len)
119{
120    if (!len) return 0;
121    if (!str->data) return -1;
122
123    if (len + str->actual_size >= str->alloc_size) {
124	if (expand_for_size(str, str->actual_size + len) < 0) {
125	    return -1;
126	}
127    }
128
129    memcpy(str->data + str->actual_size, s2, len);
130    str->actual_size += len;
131    str->data[str->actual_size] = 0;
132    return 0;
133}
134
135char const *
136dynstring_data(dynstring *str)
137{
138    return str->data;
139}
140