]> git.neil.brown.name Git - edlib.git/blob - misc.h
TODO: clean out done items.
[edlib.git] / misc.h
1 /*
2  * Copyright Neil Brown ©2015-2023 <neil@brown.name>
3  * May be distributed under terms of GPLv2 - see file:COPYING
4  *
5  * Assorted utility functions used by edlib
6  *
7  */
8 #ifndef EDLIB_MISC
9 #define EDLIB_MISC
10
11 #include <wchar.h>
12 #include "list.h"
13
14 #undef bool
15 typedef _Bool bool;
16 #define True ((bool)1)
17 #define False ((bool)0)
18
19 #define strstarts(s, prefix) (strncmp(s, prefix, sizeof(prefix)-1) == 0)
20
21 #define WERR (0xfffffffeu)
22 wint_t get_utf8(const char **cpp safe, const char *end);
23 char *safe put_utf8(char *buf safe, wchar_t ch);
24 int utf8_strlen(const char *s safe);
25 int utf8_strnlen(const char *s safe, int n);
26 int utf8_round_len(const char *text safe, int len);
27 int utf8_valid(const char *s safe);
28 static inline int utf8_bytes(wchar_t ch)
29 {
30         if (ch < 0x80)
31                 return 1;
32         else if (ch < 0x800)
33                 return 2;
34         else if (ch < 0x10000)
35                 return 3;
36         else if (ch < 0x200000)
37                 return 4;
38         else
39                 return 0;
40 }
41
42 struct buf {
43         char *b safe;
44         int len;
45         int size;
46 };
47
48 void buf_init(struct buf *b safe);
49 void buf_concat(struct buf *b safe, const char *s safe);
50 void buf_concat_len(struct buf *b safe, const char *s safe, int l);
51 void buf_append(struct buf *b safe, wchar_t wch);
52 void buf_append_byte(struct buf *b safe, char c);
53 void buf_resize(struct buf *b safe, int size);
54 static inline char *safe buf_final(struct buf *b safe)
55 {
56         b->b[b->len] = 0;
57         return b->b;
58 }
59 static inline void buf_reinit(struct buf *b safe)
60 {
61         b->len = 0;
62 }
63
64 /* Formatting can be embedded in text strings in some places using
65  * SOH STX ETX.
66  * SOH format-attributes STX the text ETX
67  * "the text" can contain nested SOH/STX/ETX sequences.
68  * The same can be done with
69  *  < format-attributes> the text </a>
70  * but that is being phased out.
71  */
72 #define SOH "\001"
73 #define STX "\002"
74 #define ETX "\003"
75 #define soh '\001'
76 #define stx '\002'
77 #define etx '\003'
78 /* ACK is used as a no-op. */
79 #define ack '\006'
80 #define ACK "\006"
81
82 /* Performance measurements.
83  * 1/ timers.
84  */
85 enum timetype {
86         TIME_KEY,
87         TIME_WINDOW,
88         TIME_READ,
89         TIME_SIG,
90         TIME_TIMER,
91         TIME_IDLE,
92         TIME_REFRESH,
93         TIME_MISC,
94         TIME__COUNT,
95 };
96 void time_start(enum timetype);
97 void time_stop(enum timetype);
98 void time_start_key(const char *key safe);
99 void time_stop_key(const char *key safe);
100
101 extern bool debugger_is_present(void);
102
103 void stat_count(char *name safe);
104
105 void stat_free(void);
106
107 /*
108  * Memory allocation tracking
109  */
110
111 struct mempool {
112         char *name;
113         long bytes;
114         long allocations;
115         long max_bytes;
116         struct list_head linkage;
117 };
118
119 #define MEMPOOL(_name)                                                  \
120         struct mempool mem ## _name = {                         \
121                 .name = #_name,                                 \
122                 .linkage = LIST_HEAD_INIT(mem ## _name.linkage),        \
123         }
124 #define MEMPOOL_DECL(_name) struct mempool mem ## _name;
125
126 void *safe do_alloc(struct mempool *pool safe, int size, int zero);
127 void do_unalloc(struct mempool *pool safe, const void *obj, int size);
128
129 #define alloc(var, pool)                                                \
130         do { var = do_alloc(&mem##pool, sizeof((var)[0]), 1); } while (0)
131
132 #define alloc_buf(size, pool) do_alloc(&mem##pool, size, 0)
133 #define alloc_zbuf(size, pool) do_alloc(&mem##pool, size, 1)
134
135 #define unalloc(var, pool)                                              \
136         do { do_unalloc(&mem##pool, var, sizeof((var)[0])); (var)=NULL; } while (0)
137
138 #define unalloc_buf(var, size, pool)                                    \
139         do { do_unalloc(&mem##pool, var, size); (var) = NULL; } while(0)
140
141 #define unalloc_str(var, pool)                                          \
142         unalloc_buf(var, strlen(var)+1, pool)
143
144 #define unalloc_safe(var, pool)                                         \
145         do { do_unalloc(&mem##pool, var, sizeof((var)[0])); (var)=safe_cast NULL; } while (0)
146
147 #define unalloc_buf_safe(var, size, pool)                               \
148         do { do_unalloc(&mem##pool, var, size); (var) = safe_cast NULL; } while(0)
149
150 #define unalloc_str_safe(var, pool)                                             \
151         unalloc_buf_safe(var, strlen(var)+1, pool)
152
153 /* attrs parsing */
154
155 /* Sequentially set _attr to the an attr name, and _val to
156  * either the val (following ":") or NULL.
157  * _attr is valid up to : or , or < space and _val is valid up to , or <space
158  * _c is the start which will be updates, and _end is the end which
159  * must point to , or nul or a control char
160  */
161 #define foreach_attr(_attr, _val, _c, _end)                     \
162         for (_attr = _c, _val = afind_val(&_c, _end);           \
163              _attr;                                             \
164              _attr = _c, _val = afind_val(&_c, _end))
165 const char *afind_val(const char **cp safe, const char *end);
166 char *aupdate(char **cp safe, const char *v);
167 bool amatch(const char *a safe, const char *m safe);
168 bool aprefix(const char *a safe, const char *m safe);
169 long anum(const char *v safe);
170
171 #endif /* EDLIB_MISC */