Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* dynstr.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Port                                                                   */
6
/*                                                                           */
7
/* Handling of strings with dynamic allocation                               */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include <stdio.h>
12
#include <string.h>
13
#include <stdlib.h>
14
#include <errno.h>
15
 
16
#include "dynstr.h"
17
 
18
static void check_dynamic(const as_dynstr_t *p_str)
19
{
20
  if (!p_str->dynamic)
21
  {
22
    fprintf(stderr, "attemt to resize non-dynamic string\n");
23
    abort();
24
  }
25
}
26
 
27
/*!------------------------------------------------------------------------
28
 * \fn     as_dynstr_ini(as_dynstr_t *p_str, size_t AllocLen)
29
 * \brief  initialize empty string with given capacity
30
 * \param  p_str string to initialize
31
 * \param  AllocLen initial alloc length
32
 * ------------------------------------------------------------------------ */
33
 
34
void as_dynstr_ini(as_dynstr_t *p_str, size_t ini_capacity)
35
{
36
  p_str->p_str = ini_capacity ? (char*)malloc(ini_capacity) : NULL;
37
  p_str->capacity = p_str->p_str ? ini_capacity : 0;
38
  p_str->dynamic = !!p_str->p_str;
39
  memset(p_str->p_str, 0, p_str->capacity);
40
}
41
 
42
/*!------------------------------------------------------------------------
43
 * \fn     as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src)
44
 * \brief  initialize empty string from other string
45
 * \param  p_str string to initialize
46
 * \param  p_src string to clone
47
 * ------------------------------------------------------------------------ */
48
 
49
void as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src)
50
{
51
  p_str->p_str = (char*)malloc(p_src->capacity);
52
  if (p_str->p_str)
53
  {
54
    strcpy(p_str->p_str, p_src->p_str);
55
    p_str->capacity = p_src->capacity;
56
    p_str->dynamic = 1;
57
  }
58
  else
59
  {
60
    p_str->capacity = 0;
61
    p_str->dynamic = 0;
62
  }
63
}
64
 
65
/*!------------------------------------------------------------------------
66
 * \fn     as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src)
67
 * \brief  initialize string from C string
68
 * \param  p_str string to initialize
69
 * \param  p_src init source
70
 * ------------------------------------------------------------------------ */
71
 
72
void as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src)
73
{
74
  size_t capacity = as_dynstr_roundup_len(strlen(p_src));
75
 
76
  p_str->p_str = (char*)malloc(capacity);
77
  if (p_str->p_str)
78
  {
79
    strcpy(p_str->p_str, p_src);
80
    p_str->capacity = capacity;
81
    p_str->dynamic = 1;
82
  }
83
  else
84
  {
85
    p_str->capacity = 0;
86
    p_str->dynamic = 0;
87
  }
88
}
89
 
90
/*!------------------------------------------------------------------------
91
 * \fn     as_dynstr_realloc(as_dynstr_t *p_str, size_t new_capacity)
92
 * \brief  shrink/grow string's capacity
93
 * \param  p_str string to adapt
94
 * \param  new_capacity new capacity
95
 * \return 0 if success or error code
96
 * ------------------------------------------------------------------------ */
97
 
98
int as_dynstr_realloc(as_dynstr_t *p_str, size_t new_capacity)
99
{
100
  char *p_new;
101
  size_t old_capacity;
102
 
103
  check_dynamic(p_str);
104
  p_new = (char*)realloc(p_str->p_str, new_capacity);
105
  old_capacity = p_str->capacity;
106
  if (p_new)
107
  {
108
    p_str->p_str = p_new;
109
    p_str->capacity = new_capacity;
110
    if (new_capacity > old_capacity)
111
      memset(p_str->p_str + old_capacity, 0, new_capacity - old_capacity);
112
    else if (new_capacity > 0)
113
      p_str->p_str[new_capacity - 1] = '\0';
114
    return 0;
115
  }
116
  else
117
    return ENOMEM;
118
}
119
 
120
/*!------------------------------------------------------------------------
121
 * \fn     as_dynstr_free(as_dynstr_t *p_str)
122
 * \brief  free/destroy string
123
 * \param  p_str string to handle
124
 * ------------------------------------------------------------------------ */
125
 
126
void as_dynstr_free(as_dynstr_t *p_str)
127
{
128
  if (p_str->dynamic && p_str->p_str)
129
    free(p_str->p_str);
130
  p_str->p_str = NULL;
131
  p_str->capacity = 0;
132
  p_str->dynamic = 0;
133
}
134
 
135
/*!------------------------------------------------------------------------
136
 * \fn     as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src)
137
 * \brief  set string from other string
138
 * \param  p_str string to set
139
 * \param  p_src init source
140
 * \return actual # of characters copied
141
 * ------------------------------------------------------------------------ */
142
 
143
size_t as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src)
144
{
145
  return as_dynstr_copy_c_str(p_dest, p_src->p_str);
146
}
147
 
148
/*!------------------------------------------------------------------------
149
 * \fn     as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src)
150
 * \brief  set string from C string
151
 * \param  p_str string to set
152
 * \param  p_src init source
153
 * \return actual # of characters copied
154
 * ------------------------------------------------------------------------ */
155
 
156
size_t as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src)
157
{
158
  size_t len = strlen(p_src);
159
 
160
  if ((len >= p_dest->capacity) && p_dest->dynamic)
161
    as_dynstr_realloc(p_dest, as_dynstr_roundup_len(len));
162
 
163
  if (len >= p_dest->capacity)
164
    len = p_dest->capacity - 1;
165
  memcpy(p_dest->p_str, p_src, len);
166
  p_dest->p_str[len] = '\0';
167
  return len;
168
}
169
 
170
/*!------------------------------------------------------------------------
171
 * \fn     as_dynstr_append(as_dynstr_t *p_dest, const char *p_src, size_t src_len)
172
 * \brief  extend string
173
 * \param  p_dest string to extend
174
 * \param  p_src what to append
175
 * \param  src_len how much to append
176
 * \return actual # of bytes transferred
177
 * ------------------------------------------------------------------------ */
178
 
179
size_t as_dynstr_append(as_dynstr_t *p_dest, const char *p_src, size_t src_len)
180
{
181
  size_t dest_len = strlen(p_dest->p_str);
182
 
183
  if ((dest_len + src_len + 1 > p_dest->capacity) && p_dest->dynamic)
184
    as_dynstr_realloc(p_dest, as_dynstr_roundup_len(dest_len + src_len));
185
  if (src_len >= p_dest->capacity - dest_len)
186
    src_len = p_dest->capacity - dest_len - 1;
187
  memcpy(p_dest->p_str + dest_len, p_src, src_len);
188
  p_dest->p_str[dest_len + src_len] = '\0';
189
  return src_len;
190
}
191
 
192
/*!------------------------------------------------------------------------
193
 * \fn     as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src)
194
 * \brief  extend string
195
 * \param  p_dest string to extend
196
 * \param  p_src what to append
197
 * \return actual # of bytes transferred
198
 * ------------------------------------------------------------------------ */
199
 
200
size_t as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src)
201
{
202
  return as_dynstr_append(p_dest, p_src, strlen(p_src));
203
}
204
 
205
/*!------------------------------------------------------------------------
206
 * \fn     as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str)
207
 * \brief  debug helper
208
 * \param  p_file where to dump
209
 * \param  p_str string to dump
210
 * ------------------------------------------------------------------------ */
211
 
212
void as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str)
213
{
214
  const char *p_run;
215
 
216
  fprintf(p_file, "[%u]", (unsigned)p_str->capacity);
217
  for (p_run = p_str->p_str; *p_run; p_run++) fprintf(p_file, " %02x", *p_run & 0xff);
218
  fprintf(p_file, "\n");
219
}