summaryrefslogtreecommitdiffstats
path: root/src/collectors/log2journal/log2journal-txt.h
blob: f68b85a3da0c8ba8b5f4d939b0c7409b87874474 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NETDATA_LOG2JOURNAL_TXT_H
#define NETDATA_LOG2JOURNAL_TXT_H

#include "log2journal.h"

// ----------------------------------------------------------------------------
// A dynamically sized, reusable text buffer,
// allowing us to be fast (no allocations during iterations) while having the
// smallest possible allocations.

typedef struct txt_l2j {
    char *txt;
    uint32_t size;
    uint32_t len;
} TXT_L2J;

static inline void txt_l2j_cleanup(TXT_L2J *t) {
    if(!t)
        return;

    if(t->txt)
        freez(t->txt);

    t->txt = NULL;
    t->size = 0;
    t->len = 0;
}

#define TXT_L2J_ALLOC_ALIGN 1024

static inline size_t txt_l2j_compute_new_size(size_t old_size, size_t required_size) {
    size_t size = (required_size % TXT_L2J_ALLOC_ALIGN == 0) ? required_size : required_size + TXT_L2J_ALLOC_ALIGN;
    size = (size / TXT_L2J_ALLOC_ALIGN) * TXT_L2J_ALLOC_ALIGN;

    if(size < old_size * 2)
        size = old_size * 2;

    return size;
}

static inline void txt_l2j_resize(TXT_L2J *dst, size_t required_size, bool keep) {
    if(required_size <= dst->size)
        return;

    size_t new_size = txt_l2j_compute_new_size(dst->size, required_size);

    if(keep && dst->txt)
        dst->txt = reallocz(dst->txt, new_size);
    else {
        txt_l2j_cleanup(dst);
        dst->txt = mallocz(new_size);
        dst->len = 0;
    }

    dst->size = new_size;
}

static inline void txt_l2j_set(TXT_L2J *dst, const char *s, int32_t len) {
    if(!s || !*s || len == 0) {
        s = "";
        len = 0;
    }

    if(len == -1)
        len = (int32_t)strlen(s);

    txt_l2j_resize(dst, len + 1, false);
    memcpy(dst->txt, s, len);
    dst->txt[len] = '\0';
    dst->len = len;
}

static inline void txt_l2j_append(TXT_L2J *dst, const char *s, int32_t len) {
    if(!dst->txt || !dst->len)
        txt_l2j_set(dst, s, len);

    else {
        if(len == -1)
            len = (int32_t)strlen(s);

        txt_l2j_resize(dst, dst->len + len + 1, true);
        memcpy(&dst->txt[dst->len], s, len);
        dst->len += len;
        dst->txt[dst->len] = '\0';
    }
}

#endif //NETDATA_LOG2JOURNAL_TXT_H