$darkmode
Libical API Documentation 4.0 STABLE VERSION Visit the v3.0 documentation
vcardstructured.c
Go to the documentation of this file.
1 /*======================================================================
2  FILE: vcardstructured.c
3  CREATOR: Ken Murchison 24 Aug 2022
4 
5  SPDX-FileCopyrightText: 2022, Fastmail Pty. Ltd. (https://fastmail.com)
6  SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7  ======================================================================*/
8 
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17 
18 #include "vcardstructuredimpl.h"
19 #include "vcardstructured.h"
20 #include "vcardvalue.h"
21 #include "icalerror_p.h"
22 #include "icallimits.h"
23 #include "icalmemory.h"
24 
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 static vcardstructuredtype *vcardstructured_alloc(size_t num_fields)
30 {
31  struct vcardstructuredtype_impl *st;
32 
33  st = icalmemory_new_buffer(sizeof(struct vcardstructuredtype_impl));
34  if (!st) {
36  return NULL;
37  }
38  memset(st, 0, sizeof(struct vcardstructuredtype_impl));
39 
40  if (num_fields > 0) {
41  st->field = (vcardstrarray **)icalmemory_new_buffer(num_fields * sizeof(vcardstrarray *));
42  if (!st->field) {
45  return NULL;
46  }
47  memset((void *)st->field, 0, num_fields * sizeof(vcardstrarray *));
48  st->num_alloc = num_fields;
49  }
50 
51  return st;
52 }
53 
54 static void vcardstructured_free(vcardstructuredtype *st)
55 {
56  for (size_t i = 0; i < st->num_fields; i++) {
57  if (st->field[i]) {
58  vcardstrarray_free(st->field[i]);
59  }
60  }
61  icalmemory_free_buffer((void *)st->field);
62  icalmemory_free_buffer((void *)st);
63 }
64 
66 {
67  struct vcardstructuredtype_impl *st = vcardstructured_alloc(num_fields);
68  if (!st) {
69  return st;
70  }
72 
73  st->num_fields = num_fields;
74  return st;
75 }
76 
78 {
79  struct vcardstructuredtype_impl *st = vcardstructured_alloc(0);
80  if (!st) {
81  return st;
82  }
84 
85  if (!*str) {
86  return st;
87  }
88 
89  vcardstrarray *field = vcardstrarray_new(2);
90  vcardstructured_set_field_at(st, st->num_fields, field);
91 
92  size_t cnt = 0;
93  const size_t max_chars = icallimit_get(ICAL_LIMIT_PARSE_SEARCH);
94  do {
95  char *dequoted_str = vcardvalue_strdup_and_dequote_text(&str, ",;");
96 
97  if (*str == ',' || field->num_elements || strlen(dequoted_str)) {
98  vcardstrarray_append(field, dequoted_str);
99  }
100  icalmemory_free_buffer(dequoted_str);
101 
102  if (*str == ';') {
103  /* end of field */
104  field = vcardstrarray_new(2);
105  vcardstructured_set_field_at(st, st->num_fields, field);
106  }
107 
108  } while (*str++ != '\0' && cnt++ < max_chars);
109 
110  return st;
111 }
112 
114 {
115  icalerror_check_arg_rv((st != NULL), "st");
116 
117  st->refcount++;
118 }
119 
121 {
122  icalerror_check_arg_rv((st != NULL), "st");
123  icalerror_check_arg_rv((st->refcount > 0), "st->refcount > 0");
124 
125  st->refcount--;
126 
127  if (st->refcount != 0) {
128  return;
129  }
130 
131  vcardstructured_free(st);
132 }
133 
135 {
136  icalerror_check_arg_rz((st != NULL), "st");
137 
138  struct vcardstructuredtype_impl *clone_st = vcardstructured_alloc(st->num_fields);
139  if (!clone_st) {
140  return NULL;
141  }
142  vcardstructured_ref(clone_st);
143 
144  clone_st->num_fields = st->num_fields;
145  for (size_t i = 0; i < st->num_fields; i++) {
146  clone_st->field[i] = vcardstrarray_clone(st->field[i]);
147  }
148 
149  return clone_st;
150 }
151 
153 {
154  icalerror_check_arg_rz((st != NULL), "st");
155  return st->num_fields;
156 }
157 
159  size_t num_fields)
160 {
161  icalerror_check_arg_rv((st != NULL), "st");
162 
163  if (num_fields > st->num_alloc) {
164  size_t new_alloc = ((num_fields + 7) / 8) * 8;
165  vcardstrarray **new_field = (vcardstrarray **)icalmemory_new_buffer(new_alloc * sizeof(vcardstrarray *));
166  if (!new_field) {
168  return;
169  }
170 
171  if (st->num_fields && st->field) {
172  memcpy((void *)new_field, (void *)st->field, st->num_fields * sizeof(vcardstrarray *));
173  }
174  memset((void *)(new_field + st->num_alloc), 0,
175  (new_alloc - st->num_alloc) * sizeof(vcardstrarray *));
176 
177  icalmemory_free_buffer((void *)st->field);
178  st->field = new_field;
179  st->num_alloc = new_alloc;
180  }
181 
182  for (size_t i = num_fields; i < st->num_fields; i++) {
183  vcardstrarray_free(st->field[i]);
184  st->field[i] = NULL;
185  }
186 
187  st->num_fields = num_fields;
188 }
189 
191  size_t position)
192 {
193  icalerror_check_arg_rz((st != NULL), "st");
194  icalerror_check_arg_rz((st->num_fields > position), "position");
195 
196  return st->field[position];
197 }
198 
200  size_t position,
201  vcardstrarray *field)
202 {
203  icalerror_check_arg_rv((st != NULL), "st");
204 
205  if (position >= st->num_fields) {
206  vcardstructured_set_num_fields(st, position + 1);
208  return;
209  }
210  }
211 
212  vcardstrarray_free(st->field[position]);
213  st->field[position] = field;
214 }
Defines the data structure representing vCard structured values.
struct vcardstructuredtype_impl vcardstructuredtype
Represents a decoded, structured text value.
Common memory management routines.
void vcardstructured_set_num_fields(vcardstructuredtype *st, size_t num_fields)
Sets the number of fields in a vcardstructuredtype.
void icalmemory_free_buffer(void *buf)
Releases a buffer.
Definition: icalmemory.c:355
size_t icallimit_get(icallimits_kind kind)
Definition: icallimits.c:29
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition: icalerror.c:90
void vcardstructured_ref(vcardstructuredtype *st)
Increments the reference count of the vcardstructuredtype.
void vcardstructured_unref(vcardstructuredtype *st)
Decrements the reference count of the vcardstructuredtype.
vcardstructuredtype * vcardstructured_new(size_t num_fields)
Creates a new instance of vcardstructuredtype.
size_t vcardstructured_num_fields(const vcardstructuredtype *st)
Returns the number of fields in a vcardstructuredtype.
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
Definition: icalmemory.c:315
Defines the interface for getting/setting internal library limits.
Defines the data structure representing vCard values.
vcardstructuredtype * vcardstructured_new_from_string(const char *str)
Creates a new instance of vcardstructuredtype from a string.
#define icalerrno
Access the current icalerrno value.
Definition: icalerror.h:133
void vcardstructured_set_field_at(vcardstructuredtype *st, size_t position, vcardstrarray *field)
Sets the field at the given position in a vcardstructuredtype.
vcardstructuredtype * vcardstructured_clone(const vcardstructuredtype *st)
Clones a vcardstructuredtype.
vcardstrarray * vcardstructured_field_at(const vcardstructuredtype *st, size_t position)
Returns the field at the given position in a vcardstructuredtype.