Make API CTF-agnostic
[babeltrace.git] / common / common.c
index 3020b60ffd1a1bbd39d6fc1ba16f65736883b198..1c49a465ccfcee27ec228fa2c1862cbe8717fbe2 100644 (file)
 
 #include <unistd.h>
 #include <string.h>
+#include <inttypes.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <assert.h>
+#include <babeltrace/assert-internal.h>
+#include <stdarg.h>
 #include <ctype.h>
 #include <glib.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
 #include <stdbool.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/common-internal.h>
@@ -190,7 +194,7 @@ int bt_common_append_plugin_path_dirs(const char *paths, GPtrArray *dirs)
        const char *end;
        size_t init_dirs_len;
 
-       assert(dirs);
+       BT_ASSERT(dirs);
        init_dirs_len = dirs->len;
 
        if (!paths) {
@@ -573,7 +577,7 @@ bool bt_common_string_is_printable(const char *input)
 {
        const char *ch;
        bool printable = true;
-       assert(input);
+       BT_ASSERT(input);
 
        for (ch = input; *ch != '\0'; ch++) {
                if (!isprint(*ch) && *ch != '\n' && *ch != '\r' &&
@@ -627,7 +631,7 @@ struct bt_common_lttng_live_url_parts bt_common_parse_lttng_live_url(
        const char *at = url;
        size_t end_pos;
 
-       assert(url);
+       BT_ASSERT(url);
        memset(&parts, 0, sizeof(parts));
        parts.port = -1;
 
@@ -796,7 +800,7 @@ void bt_common_normalize_star_glob_pattern(char *pattern)
        char *np;
        bool got_star = false;
 
-       assert(pattern);
+       BT_ASSERT(pattern);
 
        for (p = pattern, np = pattern; *p != '\0'; p++) {
                switch (*p) {
@@ -1004,7 +1008,7 @@ retry:
         *                         ^  ^ SUCCESS
         */
        while ((c - candidate) < candidate_len && *c != '\0') {
-               assert(*c);
+               BT_ASSERT(*c);
 
                if (at_end_of_pattern(p, pattern, pattern_len)) {
                        goto end_of_pattern;
@@ -1093,7 +1097,7 @@ void append_path_parts(const char *path, GPtrArray *parts)
                        if (ch - last > 0) {
                                GString *part = g_string_new(NULL);
 
-                               assert(part);
+                               BT_ASSERT(part);
                                g_string_append_len(part, last, ch - last);
                                g_ptr_array_add(parts, part);
                        }
@@ -1122,7 +1126,7 @@ GString *bt_common_normalize_path(const char *path, const char *wd)
        char *tmp;
        GString *norm_path = NULL;
 
-       assert(path);
+       BT_ASSERT(path);
 
        tmp = _fullpath(NULL, path, PATH_MAX);
        if (!tmp) {
@@ -1154,7 +1158,7 @@ GString *bt_common_normalize_path(const char *path, const char *wd)
        GString *norm_path;
        GPtrArray *parts = NULL;
 
-       assert(path);
+       BT_ASSERT(path);
        norm_path = g_string_new(G_DIR_SEPARATOR_S);
        if (!norm_path) {
                goto error;
@@ -1246,3 +1250,320 @@ size_t bt_common_get_page_size(void)
 
        return page_size;
 }
+
+#define BUF_STD_APPEND(...)                                            \
+       do {                                                            \
+               char _tmp_fmt[64];                                      \
+               int _count;                                             \
+               size_t _size = buf_size - (size_t) (*buf_ch - buf);     \
+               size_t _tmp_fmt_size = (size_t) (fmt_ch - *out_fmt_ch); \
+               strncpy(_tmp_fmt, *out_fmt_ch, _tmp_fmt_size);          \
+               _tmp_fmt[_tmp_fmt_size] = '\0';                         \
+               _count = snprintf(*buf_ch, _size, _tmp_fmt, __VA_ARGS__); \
+               BT_ASSERT(_count >= 0);                                 \
+               *buf_ch += MIN(_count, _size);                          \
+       } while (0)
+
+#define BUF_STD_APPEND_SINGLE_ARG(_type)                               \
+       do {                                                            \
+               _type _arg = va_arg(*args, _type);                      \
+               BUF_STD_APPEND(_arg);                                   \
+       } while (0)
+
+static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
+               size_t buf_size, const char **out_fmt_ch, va_list *args)
+{
+       const char *fmt_ch = *out_fmt_ch;
+       enum LENGTH_MODIFIER {
+               LENGTH_MOD_H,
+               LENGTH_MOD_HH,
+               LENGTH_MOD_NONE,
+               LENGTH_MOD_LOW_L,
+               LENGTH_MOD_LOW_LL,
+               LENGTH_MOD_UP_L,
+               LENGTH_MOD_Z,
+       } length_mod = LENGTH_MOD_NONE;
+
+       /* skip '%' */
+       fmt_ch++;
+
+       if (*fmt_ch == '%') {
+               fmt_ch++;
+               **buf_ch = '%';
+               (*buf_ch)++;
+               goto update_rw_fmt;
+       }
+
+       /* flags */
+       for (;;) {
+               switch (*fmt_ch) {
+                       case '-':
+                       case '+':
+                       case ' ':
+                       case '#':
+                       case '0':
+                       case '\'':
+                               fmt_ch++;
+                               continue;
+                       default:
+                               break;
+               }
+               break;
+       }
+
+       /* width */
+       for (;;) {
+               if (*fmt_ch < '0' || *fmt_ch > '9') {
+                       break;
+               }
+
+               fmt_ch++;
+       }
+
+       /* precision */
+       if (*fmt_ch == '.') {
+               fmt_ch++;
+
+               for (;;) {
+                       if (*fmt_ch < '0' || *fmt_ch > '9') {
+                               break;
+                       }
+
+                       fmt_ch++;
+               }
+       }
+
+       /* format (PRI*64) */
+       if (strncmp(fmt_ch, PRId64, sizeof(PRId64) - 1) == 0) {
+               fmt_ch += sizeof(PRId64);
+               BUF_STD_APPEND_SINGLE_ARG(int64_t);
+               goto update_rw_fmt;
+       } else if (strncmp(fmt_ch, PRIu64, sizeof(PRIu64) - 1) == 0) {
+               fmt_ch += sizeof(PRIu64);
+               BUF_STD_APPEND_SINGLE_ARG(uint64_t);
+               goto update_rw_fmt;
+       } else if (strncmp(fmt_ch, PRIx64, sizeof(PRIx64) - 1) == 0) {
+               fmt_ch += sizeof(PRIx64);
+               BUF_STD_APPEND_SINGLE_ARG(uint64_t);
+               goto update_rw_fmt;
+       } else if (strncmp(fmt_ch, PRIX64, sizeof(PRIX64) - 1) == 0) {
+               fmt_ch += sizeof(PRIX64);
+               BUF_STD_APPEND_SINGLE_ARG(uint64_t);
+               goto update_rw_fmt;
+       } else if (strncmp(fmt_ch, PRIo64, sizeof(PRIo64) - 1) == 0) {
+               fmt_ch += sizeof(PRIo64);
+               BUF_STD_APPEND_SINGLE_ARG(uint64_t);
+               goto update_rw_fmt;
+       } else if (strncmp(fmt_ch, PRIi64, sizeof(PRIi64) - 1) == 0) {
+               fmt_ch += sizeof(PRIi64);
+               BUF_STD_APPEND_SINGLE_ARG(int64_t);
+               goto update_rw_fmt;
+       }
+
+       // length modifier
+       switch (*fmt_ch) {
+               case 'h':
+                       length_mod = LENGTH_MOD_H;
+                       fmt_ch++;
+
+                       if (*fmt_ch == 'h') {
+                               length_mod = LENGTH_MOD_HH;
+                               fmt_ch++;
+                               break;
+                       }
+                       break;
+               case 'l':
+                       length_mod = LENGTH_MOD_LOW_L;
+                       fmt_ch++;
+
+                       if (*fmt_ch == 'l') {
+                               length_mod = LENGTH_MOD_LOW_LL;
+                               fmt_ch++;
+                               break;
+                       }
+                       break;
+               case 'L':
+                       length_mod = LENGTH_MOD_UP_L;
+                       fmt_ch++;
+                       break;
+               case 'z':
+                       length_mod = LENGTH_MOD_Z;
+                       fmt_ch++;
+                       break;
+               default:
+                       break;
+       }
+
+       // format
+       switch (*fmt_ch) {
+       case 'c':
+       {
+               fmt_ch++;
+
+               switch (length_mod) {
+               case LENGTH_MOD_NONE:
+                       BUF_STD_APPEND_SINGLE_ARG(int);
+                       break;
+               case LENGTH_MOD_LOW_L:
+                       BUF_STD_APPEND_SINGLE_ARG(wint_t);
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       }
+       case 's':
+               fmt_ch++;
+
+               switch (length_mod) {
+               case LENGTH_MOD_NONE:
+                       BUF_STD_APPEND_SINGLE_ARG(char *);
+                       break;
+               case LENGTH_MOD_LOW_L:
+                       BUF_STD_APPEND_SINGLE_ARG(wchar_t *);
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       case 'd':
+       case 'i':
+               fmt_ch++;
+
+               switch (length_mod) {
+               case LENGTH_MOD_NONE:
+               case LENGTH_MOD_H:
+               case LENGTH_MOD_HH:
+                       BUF_STD_APPEND_SINGLE_ARG(int);
+                       break;
+               case LENGTH_MOD_LOW_L:
+                       BUF_STD_APPEND_SINGLE_ARG(long);
+                       break;
+               case LENGTH_MOD_LOW_LL:
+                       BUF_STD_APPEND_SINGLE_ARG(long long);
+                       break;
+               case LENGTH_MOD_Z:
+                       BUF_STD_APPEND_SINGLE_ARG(size_t);
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       case 'o':
+       case 'x':
+       case 'X':
+       case 'u':
+               fmt_ch++;
+
+               switch (length_mod) {
+               case LENGTH_MOD_NONE:
+               case LENGTH_MOD_H:
+               case LENGTH_MOD_HH:
+                       BUF_STD_APPEND_SINGLE_ARG(unsigned int);
+                       break;
+               case LENGTH_MOD_LOW_L:
+                       BUF_STD_APPEND_SINGLE_ARG(unsigned long);
+                       break;
+               case LENGTH_MOD_LOW_LL:
+                       BUF_STD_APPEND_SINGLE_ARG(unsigned long long);
+                       break;
+               case LENGTH_MOD_Z:
+                       BUF_STD_APPEND_SINGLE_ARG(size_t);
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       case 'f':
+       case 'F':
+       case 'e':
+       case 'E':
+       case 'g':
+       case 'G':
+               fmt_ch++;
+
+               switch (length_mod) {
+               case LENGTH_MOD_NONE:
+                       BUF_STD_APPEND_SINGLE_ARG(double);
+                       break;
+               case LENGTH_MOD_UP_L:
+                       BUF_STD_APPEND_SINGLE_ARG(long double);
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       case 'p':
+               fmt_ch++;
+
+               if (length_mod == LENGTH_MOD_NONE) {
+                       BUF_STD_APPEND_SINGLE_ARG(void *);
+               } else {
+                       abort();
+               }
+               break;
+       default:
+               abort();
+       }
+
+update_rw_fmt:
+       *out_fmt_ch = fmt_ch;
+}
+
+BT_HIDDEN
+void bt_common_custom_vsnprintf(char *buf, size_t buf_size,
+               char intro,
+               bt_common_handle_custom_specifier_func handle_specifier,
+               void *priv_data, const char *fmt, va_list *args)
+{
+       const char *fmt_ch = fmt;
+       char *buf_ch = buf;
+
+       BT_ASSERT(buf);
+       BT_ASSERT(fmt);
+       BT_ASSERT(*args);
+
+       while (*fmt_ch != '\0') {
+               switch (*fmt_ch) {
+               case '%':
+                       BT_ASSERT(fmt_ch[1] != '\0');
+
+                       if (fmt_ch[1] == intro) {
+                               handle_specifier(priv_data, &buf_ch,
+                                       buf_size - (size_t) (buf_ch - buf),
+                                       &fmt_ch, args);
+                       } else {
+                               handle_conversion_specifier_std(buf, &buf_ch,
+                                       buf_size, &fmt_ch, args);
+                       }
+
+                       if (buf_ch >= buf + buf_size - 1) {
+                               fmt_ch = "";
+                       }
+                       break;
+               default:
+                       *buf_ch = *fmt_ch;
+                       buf_ch++;
+                       if (buf_ch >= buf + buf_size - 1) {
+                               fmt_ch = "";
+                       }
+
+                       fmt_ch++;
+               }
+       }
+
+       *buf_ch = '\0';
+}
+
+BT_HIDDEN
+void bt_common_custom_snprintf(char *buf, size_t buf_size,
+               char intro,
+               bt_common_handle_custom_specifier_func handle_specifier,
+               void *priv_data, const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       bt_common_custom_vsnprintf(buf, buf_size, intro, handle_specifier,
+               priv_data, fmt, &args);
+       va_end(args);
+}
This page took 0.028584 seconds and 4 git commands to generate.