RCube
Rcube Rest Server calculates sail routes based on Grib files and sailing boat polar files
Loading...
Searching...
No Matches
glibwrapper.h
Go to the documentation of this file.
1#include <stddef.h>
2#include <string.h>
3#include <math.h>
4#define G_PI 3.14159265358979323846
5#define MIN(i, j) (((i) < (j)) ? (i) : (j))
6#define MAX(i, j) (((i) > (j)) ? (i) : (j))
7#define CLAMP(x, lo, hi) ( ((x) < (lo)) ? (lo) : ( ((x) > (hi)) ? (hi) : (x)) )
8#define N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0])) // GLIB like
9#define g_strlcpy(dest, src, size) strlcpy((dest),(src),(size))
10#define g_strlcat(dest, src, size) strlcat((dest),(src),(size))
11
12#include <string.h> /* strlen, memmove */
13#include <stdbool.h>
14
15/* mini_gstrsplit.h — drop-in sans GLib */
16#pragma once
17#include <stdlib.h>
18#include <string.h>
19#include <limits.h>
20
21/*: Length of array of string NULL terminated (like GLib g_strv_length) */
22static inline size_t g_strv_length (char * const *strv) {
23 if (!strv) return 0;
24 size_t n = 0;
25 while (strv[n]) n++;
26 return n;
27}
28
30static inline void g_strfreev(char **strv) {
31 if (!strv) return;
32 for (char **p = strv; *p; ++p) free(*p);
33 free(strv);
34}
35
37static inline char **g_strsplit(const char *string,
38 const char *delimiter,
39 int max_tokens) {
40 if (!string) return NULL;
41 size_t dlen = (delimiter && *delimiter) ? strlen(delimiter) : 0;
42
43 if (*string == '\0') {
44 char **v = malloc(sizeof *v);
45 if (!v) return NULL;
46 v[0] = NULL;
47 return v;
48 }
49
50 // Empty delimitor or max_tokens == 1 => no split total sting is returned
51 if (dlen == 0 || max_tokens == 1) {
52 char **v = (char**)malloc(2 * sizeof *v);
53 if (!v) return NULL;
54 v[0] = strdup(string);
55 if (!v[0]) { free(v); return NULL; }
56 v[1] = NULL;
57 return v;
58 }
59
60 if (max_tokens < 1) max_tokens = INT_MAX;
61
62 size_t cap = 8, n = 0;
63 char **v = (char**)malloc((cap + 1) * sizeof *v);
64 if (!v) return NULL;
65
66 const char *p = string;
67 for (;;) {
68 // If limit reached, last element is the reminder (including delimitors)
69 if (n == (size_t)(max_tokens - 1)) {
70 v[n] = strdup(p);
71 if (!v[n]) goto oom;
72 n++;
73 break;
74 }
75
76 const char *q = strstr(p, delimiter);
77 if (!q) { // last
78 v[n] = strdup(p);
79 if (!v[n]) goto oom;
80 n++;
81 break;
82 }
83
84 size_t len = (size_t)(q - p); // can be 0 => empty element remain
85 char *tok = (char*)malloc(len + 1);
86 if (!tok) goto oom;
87 memcpy(tok, p, len);
88 tok[len] = '\0';
89 v[n++] = tok;
90
91 if (n + 1 > cap) { // +1 for final NULL
92 cap *= 2;
93 char **nv = (char**)realloc(v, (cap + 1) * sizeof *nv);
94 if (!nv) goto oom;
95 v = nv;
96 }
97 p = q + dlen;
98 }
99 v[n] = NULL;
100 return v;
101
102oom:
103 for (size_t i = 0; i < n; i++) free(v[i]);
104 free(v);
105 return NULL;
106}
107
108
110static inline bool g_ascii_isspace (unsigned char c) {
111 return c == ' ' || (c >= '\t' && c <= '\r'); // \t..\r include \t \n \v \f \r */
112}
113
115static inline char *g_strstrip (char *s) {
116 if (!s) return NULL;
117
118 // skip leading
119 char *start = s;
120 while (*start && g_ascii_isspace ((unsigned char)*start)) start++;
121
122 // find end (after skip)
123 char *end = start + strlen(start);
124 while (end > start && g_ascii_isspace((unsigned char)end[-1])) end--;
125
126 // length after trim
127 size_t len = (size_t)(end - start);
128
129 if (start != s) memmove(s, start, len);
130 s[len] = '\0';
131 return s;
132}
133
134// Replace all 'delims' with 'repl' (g_strdelimit)
135static inline void g_strdelimit (char *s, const char *delims, char repl) {
136 if (!s || !delims) return;
137 for (char *p = s; *p; ++p)
138 if (strchr(delims, *p)) *p = repl;
139}
140
142static inline char *g_strdup(const char *s) {
143 return s ? strdup(s) : NULL;
144}
145
147static inline char *g_path_get_basename (const char *path) {
148 if (!path) return NULL;
149 if (*path == '\0') return strdup(".");
150
151 const char *end = path + strlen(path);
152 while (end > path && end[-1] == '/') end--; // retire finals '/'
153 if (end == path) return strdup("/"); // "/" or "///" -> "/"
154
155 const char *start = end;
156 while (start > path && start[-1] != '/') start--;
157
158 size_t len = (size_t)(end - start);
159 char *out = (char *)malloc(len + 1);
160 if (!out) return NULL;
161 memcpy(out, start, len);
162 out[len] = '\0';
163 return out;
164}
165
167static inline bool g_str_has_suffix (const char *s, const char *suffix) {
168 if (!s || !suffix) return false;
169 size_t ls = strlen(s);
170 size_t lsu = strlen(suffix);
171 if (lsu > ls) return false;
172 // Case empty suffix -> true (GLib behavior)
173 return memcmp(s + (ls - lsu), suffix, lsu) == 0;
174}
175
177static inline bool g_str_has_prefix (const char *s, const char *prefix) {
178 if (!s || !prefix) return false;
179 size_t lp = strlen(prefix);
180 return strncmp(s, prefix, lp) == 0;
181}
182
184static inline int g_atomic_int_get (int *x) {
185 return *x;
186}
187
189static inline void g_atomic_int_set (int *x, int val) {
190 *x = val;
191}
192
static void g_strdelimit(char *s, const char *delims, char repl)
static void g_atomic_int_set(int *x, int val)
Attention NOT SAFE.
static bool g_str_has_prefix(const char *s, const char *prefix)
Equivalent to Glib g_str_has_prefix.
static void g_strfreev(char **strv)
Free array with elements (like GLib g_strfreev)
Definition glibwrapper.h:30
static bool g_ascii_isspace(unsigned char c)
GLib LIKE ' ', '\t', ' ', '\v', '\f', '\r'.
static size_t g_strv_length(char *const *strv)
Definition glibwrapper.h:22
static bool g_str_has_suffix(const char *s, const char *suffix)
Equivalent to Glib g_str_has_suffix.
static int g_atomic_int_get(int *x)
Attention NOT SAFE.
static char * g_strdup(const char *s)
equivalent to GLIB
static char * g_path_get_basename(const char *path)
close to Glib g_path_get_basename
static char ** g_strsplit(const char *string, const char *delimiter, int max_tokens)
Clone of GLib g_strsplit.
Definition glibwrapper.h:37
static char * g_strstrip(char *s)
Équivalent to GLIB g_strstrip: trim in place, return s.