• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

c-ares / c-ares / 12749958868

13 Jan 2025 03:00PM UTC coverage: 91.502% (+0.004%) from 91.498%
12749958868

Pull #960

github

web-flow
Merge e617dd6da into 0518d404e
Pull Request #960: [port] Windows XP: try to support threading and event subsystems

0 of 3 new or added lines in 1 file covered. (0.0%)

3 existing lines in 3 files now uncovered.

22406 of 24487 relevant lines covered (91.5%)

12070.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.67
/src/lib/dsa/ares_array.c
1
/* MIT License
2
 *
3
 * Copyright (c) 2024 Brad House
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to deal
7
 * in the Software without restriction, including without limitation the rights
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 *
24
 * SPDX-License-Identifier: MIT
25
 */
26
#include "ares_private.h"
27
#include "ares_array.h"
28

29
#define ARES__ARRAY_MIN 4
30

31
struct ares_array {
32
  ares_array_destructor_t destruct;
33
  void                   *arr;
34
  size_t                  member_size;
35
  size_t                  cnt;
36
  size_t                  offset;
37
  size_t                  alloc_cnt;
38
};
39

40
ares_array_t *ares_array_create(size_t                  member_size,
127,428✔
41
                                ares_array_destructor_t destruct)
42
{
43
  ares_array_t *arr;
44

45
  if (member_size == 0) {
127,428✔
46
    return NULL;
1✔
47
  }
48

49
  arr = ares_malloc_zero(sizeof(*arr));
127,427✔
50
  if (arr == NULL) {
127,427✔
51
    return NULL;
46✔
52
  }
53

54
  arr->member_size = member_size;
127,381✔
55
  arr->destruct    = destruct;
127,381✔
56
  return arr;
127,381✔
57
}
58

59
size_t ares_array_len(const ares_array_t *arr)
615,360✔
60
{
61
  if (arr == NULL) {
615,360✔
62
    return 0;
6✔
63
  }
64
  return arr->cnt;
615,354✔
65
}
66

67
void *ares_array_at(ares_array_t *arr, size_t idx)
345,746✔
68
{
69
  if (arr == NULL || idx >= arr->cnt) {
345,746✔
70
    return NULL;
5✔
71
  }
72
  return (unsigned char *)arr->arr + ((idx + arr->offset) * arr->member_size);
345,741✔
73
}
74

75
const void *ares_array_at_const(const ares_array_t *arr, size_t idx)
77✔
76
{
77
  if (arr == NULL || idx >= arr->cnt) {
77✔
78
    return NULL;
5✔
79
  }
80
  return (unsigned char *)arr->arr + ((idx + arr->offset) * arr->member_size);
72✔
81
}
82

83
ares_status_t ares_array_sort(ares_array_t *arr, ares_array_cmp_t cmp)
3✔
84
{
85
  if (arr == NULL || cmp == NULL) {
3✔
86
    return ARES_EFORMERR;
1✔
87
  }
88

89
  /* Nothing to sort */
90
  if (arr->cnt < 2) {
2✔
91
    return ARES_SUCCESS;
1✔
92
  }
93

94
  qsort((unsigned char *)arr->arr + (arr->offset * arr->member_size), arr->cnt,
1✔
95
        arr->member_size, cmp);
96
  return ARES_SUCCESS;
1✔
97
}
98

99
void ares_array_destroy(ares_array_t *arr)
118,161✔
100
{
101
  size_t i;
102

103
  if (arr == NULL) {
118,161✔
104
    return;
4,686✔
105
  }
106

107
  if (arr->destruct != NULL) {
113,475✔
108
    for (i = 0; i < arr->cnt; i++) {
251,811✔
109
      arr->destruct(ares_array_at(arr, i));
138,335✔
110
    }
111
  }
112

113
  ares_free(arr->arr);
113,476✔
114
  ares_free(arr);
113,476✔
115
}
116

117
/* NOTE: this function operates on actual indexes, NOT indexes using the
118
 *       arr->offset */
119
static ares_status_t ares_array_move(ares_array_t *arr, size_t dest_idx,
10✔
120
                                     size_t src_idx)
121
{
122
  void       *dest_ptr;
123
  const void *src_ptr;
124
  size_t      nmembers;
125

126
  if (arr == NULL || dest_idx >= arr->alloc_cnt || src_idx >= arr->alloc_cnt) {
10✔
127
    return ARES_EFORMERR;
×
128
  }
129

130
  /* Nothing to do */
131
  if (dest_idx == src_idx) {
10✔
132
    return ARES_SUCCESS;
×
133
  }
134

135
  dest_ptr = (unsigned char *)arr->arr + (dest_idx * arr->member_size);
10✔
136
  src_ptr  = (unsigned char *)arr->arr + (src_idx * arr->member_size);
10✔
137

138
  /* Check to make sure shifting to the right won't overflow our allocation
139
   * boundary */
140
  if (dest_idx > src_idx && arr->cnt + (dest_idx - src_idx) > arr->alloc_cnt) {
10✔
141
    return ARES_EFORMERR;
×
142
  }
143

144
  nmembers = arr->cnt - (src_idx - arr->offset);
10✔
145
  memmove(dest_ptr, src_ptr, nmembers * arr->member_size);
10✔
146

147
  return ARES_SUCCESS;
10✔
148
}
149

150
void *ares_array_finish(ares_array_t *arr, size_t *num_members)
13,906✔
151
{
152
  void *ptr;
153

154
  if (arr == NULL || num_members == NULL) {
13,906✔
155
    return NULL;
1✔
156
  }
157

158
  /* Make sure we move data to beginning of allocation */
159
  if (arr->offset != 0) {
13,905✔
160
    if (ares_array_move(arr, 0, arr->offset) != ARES_SUCCESS) {
×
161
      return NULL;
×
162
    }
163
    arr->offset = 0;
×
164
  }
165

166
  ptr          = arr->arr;
13,905✔
167
  *num_members = arr->cnt;
13,905✔
168
  ares_free(arr);
13,905✔
169
  return ptr;
13,905✔
170
}
171

172
ares_status_t ares_array_set_size(ares_array_t *arr, size_t size)
171,871✔
173
{
174
  void *temp;
175

176
  if (arr == NULL || size == 0 || size < arr->cnt) {
171,871✔
UNCOV
177
    return ARES_EFORMERR;
×
178
  }
179

180
  /* Always operate on powers of 2 */
181
  size = ares_round_up_pow2(size);
171,871✔
182

183
  if (size < ARES__ARRAY_MIN) {
171,870✔
184
    size = ARES__ARRAY_MIN;
118,523✔
185
  }
186

187
  /* If our allocation size is already large enough, skip */
188
  if (size <= arr->alloc_cnt) {
171,870✔
189
    return ARES_SUCCESS;
82,899✔
190
  }
191

192
  temp = ares_realloc_zero(arr->arr, arr->alloc_cnt * arr->member_size,
88,971✔
193
                           size * arr->member_size);
88,971✔
194
  if (temp == NULL) {
88,973✔
195
    return ARES_ENOMEM;
12✔
196
  }
197
  arr->alloc_cnt = size;
88,961✔
198
  arr->arr       = temp;
88,961✔
199
  return ARES_SUCCESS;
88,961✔
200
}
201

202
ares_status_t ares_array_insert_at(void **elem_ptr, ares_array_t *arr,
164,569✔
203
                                   size_t idx)
204
{
205
  void         *ptr;
206
  ares_status_t status;
207

208
  if (arr == NULL) {
164,569✔
209
    return ARES_EFORMERR;
6✔
210
  }
211

212
  /* Not >= since we are allowed to append to the end */
213
  if (idx > arr->cnt) {
164,563✔
214
    return ARES_EFORMERR;
1✔
215
  }
216

217
  /* Allocate more if needed */
218
  status = ares_array_set_size(arr, arr->cnt + 1);
164,562✔
219
  if (status != ARES_SUCCESS) {
164,564✔
220
    return status;
5✔
221
  }
222

223
  /* Shift if we have memory but not enough room at the end */
224
  if (arr->cnt + 1 + arr->offset > arr->alloc_cnt) {
164,559✔
225
    status = ares_array_move(arr, 0, arr->offset);
1✔
226
    if (status != ARES_SUCCESS) {
1✔
227
      return status;
×
228
    }
229
    arr->offset = 0;
1✔
230
  }
231

232
  /* If we're inserting anywhere other than the end, we need to move some
233
   * elements out of the way */
234
  if (idx != arr->cnt) {
164,559✔
235
    status = ares_array_move(arr, idx + arr->offset + 1, idx + arr->offset);
2✔
236
    if (status != ARES_SUCCESS) {
2✔
237
      return status;
×
238
    }
239
  }
240

241
  /* Ok, we're guaranteed to have a gap where we need it, lets zero it out,
242
   * and return it */
243
  ptr = (unsigned char *)arr->arr + ((idx + arr->offset) * arr->member_size);
164,559✔
244
  memset(ptr, 0, arr->member_size);
164,559✔
245
  arr->cnt++;
164,559✔
246

247
  if (elem_ptr) {
164,559✔
248
    *elem_ptr = ptr;
164,559✔
249
  }
250

251
  return ARES_SUCCESS;
164,559✔
252
}
253

254
ares_status_t ares_array_insert_last(void **elem_ptr, ares_array_t *arr)
164,565✔
255
{
256
  return ares_array_insert_at(elem_ptr, arr, ares_array_len(arr));
164,565✔
257
}
258

259
ares_status_t ares_array_insert_first(void **elem_ptr, ares_array_t *arr)
1✔
260
{
261
  return ares_array_insert_at(elem_ptr, arr, 0);
1✔
262
}
263

264
ares_status_t ares_array_insertdata_at(ares_array_t *arr, size_t idx,
1✔
265
                                       const void *data_ptr)
266
{
267
  ares_status_t status;
268
  void         *ptr = NULL;
1✔
269

270
  status = ares_array_insert_at(&ptr, arr, idx);
1✔
271
  if (status != ARES_SUCCESS) {
1✔
272
    return status;
1✔
273
  }
274
  memcpy(ptr, data_ptr, arr->member_size);
×
275
  return ARES_SUCCESS;
×
276
}
277

278
ares_status_t ares_array_insertdata_last(ares_array_t *arr,
78,957✔
279
                                         const void   *data_ptr)
280
{
281
  ares_status_t status;
282
  void         *ptr = NULL;
78,957✔
283

284
  status = ares_array_insert_last(&ptr, arr);
78,957✔
285
  if (status != ARES_SUCCESS) {
78,957✔
286
    return status;
2✔
287
  }
288
  memcpy(ptr, data_ptr, arr->member_size);
78,955✔
289
  return ARES_SUCCESS;
78,955✔
290
}
291

292
ares_status_t ares_array_insertdata_first(ares_array_t *arr,
1✔
293
                                          const void   *data_ptr)
294
{
295
  ares_status_t status;
296
  void         *ptr = NULL;
1✔
297

298
  status = ares_array_insert_last(&ptr, arr);
1✔
299
  if (status != ARES_SUCCESS) {
1✔
300
    return status;
1✔
301
  }
302
  memcpy(ptr, data_ptr, arr->member_size);
×
303
  return ARES_SUCCESS;
×
304
}
305

306
void *ares_array_first(ares_array_t *arr)
2✔
307
{
308
  return ares_array_at(arr, 0);
2✔
309
}
310

311
void *ares_array_last(ares_array_t *arr)
17,938✔
312
{
313
  size_t cnt = ares_array_len(arr);
17,938✔
314
  if (cnt == 0) {
17,938✔
315
    return NULL;
1✔
316
  }
317
  return ares_array_at(arr, cnt - 1);
17,937✔
318
}
319

320
const void *ares_array_first_const(const ares_array_t *arr)
×
321
{
322
  return ares_array_at_const(arr, 0);
×
323
}
324

325
const void *ares_array_last_const(const ares_array_t *arr)
×
326
{
327
  size_t cnt = ares_array_len(arr);
×
328
  if (cnt == 0) {
×
329
    return NULL;
×
330
  }
331
  return ares_array_at_const(arr, cnt - 1);
×
332
}
333

334
ares_status_t ares_array_claim_at(void *dest, size_t dest_size,
10,971✔
335
                                  ares_array_t *arr, size_t idx)
336
{
337
  ares_status_t status;
338

339
  if (arr == NULL || idx >= arr->cnt) {
10,971✔
340
    return ARES_EFORMERR;
1✔
341
  }
342

343
  if (dest != NULL && dest_size < arr->member_size) {
10,970✔
344
    return ARES_EFORMERR;
×
345
  }
346

347
  if (dest) {
10,970✔
348
    memcpy(dest, ares_array_at(arr, idx), arr->member_size);
1✔
349
  }
350

351
  if (idx == 0) {
10,970✔
352
    /* Optimization, if first element, just increment offset, makes removing a
353
     * lot from the start quick */
354
    arr->offset++;
6,416✔
355
  } else if (idx != arr->cnt - 1) {
4,554✔
356
    /* Must shift entire array if removing an element from the middle. Does
357
     * nothing if removing last element other than decrement count. */
358
    status = ares_array_move(arr, idx + arr->offset, idx + arr->offset + 1);
7✔
359
    if (status != ARES_SUCCESS) {
7✔
360
      return status;
×
361
    }
362
  }
363

364
  arr->cnt--;
10,970✔
365
  return ARES_SUCCESS;
10,970✔
366
}
367

368
ares_status_t ares_array_remove_at(ares_array_t *arr, size_t idx)
10,971✔
369
{
370
  void *ptr = ares_array_at(arr, idx);
10,971✔
371
  if (arr == NULL || ptr == NULL) {
10,971✔
372
    return ARES_EFORMERR;
2✔
373
  }
374

375
  if (arr->destruct != NULL) {
10,969✔
376
    arr->destruct(ptr);
10,969✔
377
  }
378

379
  return ares_array_claim_at(NULL, 0, arr, idx);
10,969✔
380
}
381

382
ares_status_t ares_array_remove_first(ares_array_t *arr)
3✔
383
{
384
  return ares_array_remove_at(arr, 0);
3✔
385
}
386

387
ares_status_t ares_array_remove_last(ares_array_t *arr)
10,889✔
388
{
389
  size_t cnt = ares_array_len(arr);
10,889✔
390
  if (cnt == 0) {
10,889✔
391
    return ARES_EFORMERR;
1✔
392
  }
393
  return ares_array_remove_at(arr, cnt - 1);
10,888✔
394
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc