shithub: orca

Download patch

ref: 09d9d53ecece8d36d8338d9f90c76ae220367f0f
parent: 8c4845cda6f418549b5b77d9dab8b82932d8a03b
author: cancel <cancel@cancel.fm>
date: Tue Jan 7 02:20:13 EST 2020

Add start of gbstring.h/.c

Derived from gingerBill's public domain gb_string.h

--- /dev/null
+++ b/thirdparty/gbstring.c
@@ -1,0 +1,290 @@
+#include "gbstring.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Derived from gingerBill's public domain gb_string.h file.
+
+/* Examples: */
+/* C example */
+#if 0
+#include <stdio.h>
+#include <stdlib.h>
+#include "gbstring.h"
+
+int main(int argc, char **argv) {
+	gbs str = gbs_new("Hello");
+	gbs other_str = gbs_newlen(", ", 2);
+	str = gbs_catgbs(str, other_str);
+	str = gbs_cat(str, "world!");
+
+	printf("%s\n", str); // Hello, world!
+
+	printf("str length = %d\n", gbs_len(str));
+
+	str = gbs_cpy(str, "Potato soup");
+	printf("%s\n", str); // Potato soup
+
+	str = gbs_cpy(str, "Hello");
+	other_str = gbs_cpy(other_str, "Pizza");
+	if (gbs_streq(str, other_str))
+		printf("Not called\n");
+	else
+		printf("Called\n");
+
+	str = gbs_cpy(str, "Ab.;!...AHello World       ??");
+	str = gbs_trim(str, "Ab.;!. ?");
+	printf("%s\n", str); // "Hello World"
+
+	gbs_free(str);
+	gbs_free(other_str);
+
+}
+#endif
+
+typedef struct gbStringHeader {
+  size_t len;
+  size_t cap;
+} gbStringHeader;
+
+#define GB_STRING_HEADER(s) ((gbStringHeader *)s - 1)
+
+static void gbs_setlen(gbs str, size_t len) {
+  GB_STRING_HEADER(str)->len = len;
+}
+
+static void gbs_setcap(gbs str, size_t cap) {
+  GB_STRING_HEADER(str)->cap = cap;
+}
+gbs gbs_empty(void) { return gbs_newlen(NULL, 0); }
+
+gbs gbs_newlen(void const *init_str, size_t len) {
+  gbs str;
+  gbStringHeader *header;
+  size_t header_size = sizeof(gbStringHeader);
+  void *ptr = malloc(header_size + len + 1);
+  if (ptr == NULL)
+    return NULL;
+  if (!init_str)
+    memset(ptr, 0, header_size + len + 1);
+
+  str = (char *)ptr + header_size;
+  header = GB_STRING_HEADER(str);
+  header->len = len;
+  header->cap = len;
+  if (len && init_str)
+    memcpy(str, init_str, len);
+  str[len] = '\0';
+
+  return str;
+}
+
+gbs gbs_new(char const *str) {
+  size_t len = str ? strlen(str) : 0;
+  return gbs_newlen(str, len);
+}
+
+void gbs_free(gbs str) {
+  if (str == NULL)
+    return;
+
+  free((gbStringHeader *)str - 1);
+}
+
+gbs gbs_dup(gbs const str) { return gbs_newlen(str, gbs_len(str)); }
+
+size_t gbs_len(gbs const str) { return GB_STRING_HEADER(str)->len; }
+
+size_t gbs_cap(gbs const str) { return GB_STRING_HEADER(str)->cap; }
+
+size_t gbs_avail(gbs const str) {
+  gbStringHeader *h = GB_STRING_HEADER(str);
+  if (h->cap > h->len)
+    return h->cap - h->len;
+  return 0;
+}
+
+void gbs_clear(gbs str) {
+  gbs_setlen(str, 0);
+  str[0] = '\0';
+}
+
+gbs gbs_catlen(gbs str, void const *other, size_t other_len) {
+  size_t curr_len = gbs_len(str);
+
+  str = gbs_makeroomfor(str, other_len);
+  if (str == NULL)
+    return NULL;
+
+  memcpy(str + curr_len, other, other_len);
+  str[curr_len + other_len] = '\0';
+  gbs_setlen(str, curr_len + other_len);
+
+  return str;
+}
+
+gbs gbs_catgbs(gbs str, gbs const other) {
+  return gbs_catlen(str, other, gbs_len(other));
+}
+
+gbs gbs_cat(gbs str, char const *other) {
+  return gbs_catlen(str, other, strlen(other));
+}
+
+gbs gbs_cpylen(gbs str, char const *cstr, size_t len) {
+  if (gbs_cap(str) < len) {
+    str = gbs_makeroomfor(str, len - gbs_len(str));
+    if (str == NULL)
+      return NULL;
+  }
+
+  memcpy(str, cstr, len);
+  str[len] = '\0';
+  gbs_setlen(str, len);
+
+  return str;
+}
+gbs gbs_cpy(gbs str, char const *cstr) {
+  return gbs_cpylen(str, cstr, strlen(cstr));
+}
+
+static void *gb__string_realloc(void *ptr, size_t old_size, size_t new_size) {
+  void *new_ptr;
+  if (!ptr)
+    return malloc(new_size);
+
+  if (new_size < old_size)
+    new_size = old_size;
+
+  if (old_size == new_size)
+    return ptr;
+
+  new_ptr = malloc(new_size);
+  if (!new_ptr)
+    return NULL;
+
+  memcpy(new_ptr, ptr, old_size);
+
+  free(ptr);
+
+  return new_ptr;
+}
+
+gbs gbs_makeroomfor(gbs str, size_t add_len) {
+  size_t len = gbs_len(str);
+  size_t new_len = len + add_len;
+  void *ptr, *new_ptr;
+  size_t available, old_size, new_size;
+
+  available = gbs_avail(str);
+  if (available >= add_len) /* Return if there is enough space left */
+    return str;
+
+  ptr = (char *)str - sizeof(gbStringHeader);
+  old_size = sizeof(gbStringHeader) + gbs_len(str) + 1;
+  new_size = sizeof(gbStringHeader) + new_len + 1;
+
+  new_ptr = gb__string_realloc(ptr, old_size, new_size);
+  if (new_ptr == NULL)
+    return NULL;
+  str = (char *)new_ptr + sizeof(gbStringHeader);
+
+  gbs_setcap(str, new_len);
+
+  return str;
+}
+
+size_t gbs_totalmemused(gbs const s) {
+  size_t cap = gbs_cap(s);
+  return sizeof(gbStringHeader) + cap;
+}
+
+bool gbs_streq(gbs const lhs, gbs const rhs) {
+  size_t lhs_len, rhs_len, i;
+  lhs_len = gbs_len(lhs);
+  rhs_len = gbs_len(rhs);
+  if (lhs_len != rhs_len)
+    return false;
+
+  for (i = 0; i < lhs_len; i++) {
+    if (lhs[i] != rhs[i])
+      return false;
+  }
+
+  return true;
+}
+
+gbs gbs_trim(gbs str, char const *cut_set) {
+  char *start, *end, *start_pos, *end_pos;
+  size_t len;
+
+  start_pos = start = str;
+  end_pos = end = str + gbs_len(str) - 1;
+
+  while (start_pos <= end && strchr(cut_set, *start_pos))
+    start_pos++;
+  while (end_pos > start_pos && strchr(cut_set, *end_pos))
+    end_pos--;
+
+  len = (start_pos > end_pos) ? 0 : ((size_t)(end_pos - start_pos) + 1);
+
+  if (str != start_pos)
+    memmove(str, start_pos, len);
+  str[len] = '\0';
+
+  gbs_setlen(str, len);
+
+  return str;
+}
+
+gbs gbs_catvprintf(gbs s, const char *fmt, va_list ap) {
+  va_list cpy;
+  char staticbuf[1024], *buf = staticbuf, *t;
+  size_t buflen = strlen(fmt) * 2;
+
+  /* We try to start using a static buffer for speed.
+     * If not possible we revert to heap allocation. */
+  if (buflen > sizeof(staticbuf)) {
+    buf = malloc(buflen);
+    if (buf == NULL)
+      return NULL;
+  } else {
+    buflen = sizeof(staticbuf);
+  }
+
+  /* Try with buffers two times bigger every time we fail to
+     * fit the string in the current buffer size. */
+  while (1) {
+    buf[buflen - 2] = '\0';
+    va_copy(cpy, ap);
+    vsnprintf(buf, buflen, fmt, cpy);
+    va_end(cpy);
+    if (buf[buflen - 2] != '\0') {
+      if (buf != staticbuf)
+        free(buf);
+      buflen *= 2;
+      buf = malloc(buflen);
+      if (buf == NULL)
+        return NULL;
+      continue;
+    }
+    break;
+  }
+
+  /* Finally concat the obtained string to the SDS string and return it. */
+  t = gbs_cat(s, buf);
+  if (buf != staticbuf)
+    free(buf);
+  return t;
+}
+
+gbs gbs_catprintf(gbs s, char const *fmt, ...) {
+  va_list ap;
+  char *t;
+  va_start(ap, fmt);
+  t = gbs_catvprintf(s, fmt, ap);
+  va_end(ap);
+  return t;
+}
+
+#undef GB_STRING_HEADER
--- /dev/null
+++ b/thirdparty/gbstring.h
@@ -1,0 +1,41 @@
+#pragma once
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef char *gbs;
+
+gbs gbs_empty(void);
+gbs gbs_newlen(void const *str, size_t len);
+gbs gbs_new(char const *str);
+void gbs_free(gbs str);
+
+gbs gbs_dup(gbs const str);
+
+size_t gbs_len(gbs const str);
+size_t gbs_cap(gbs const str);
+size_t gbs_avail(gbs const str);
+
+void gbs_clear(gbs str);
+
+gbs gbs_catlen(gbs str, void const *other, size_t len);
+gbs gbs_cat(gbs str, char const *other);
+gbs gbs_catgbs(gbs str, gbs const other);
+
+gbs gbs_cpylen(gbs str, char const *cstr, size_t len);
+gbs gbs_cpy(gbs str, char const *cstr);
+
+gbs gbs_makeroomfor(gbs str, size_t add_len);
+
+bool gbs_streq(gbs const lhs, gbs const rhs);
+
+gbs gbs_trim(gbs str, char const *cut_set);
+
+gbs gbs_catvprintf(gbs str, const char *fmt, va_list ap);
+gbs gbs_catprintf(gbs str, char const *fmt, ...)
+#ifdef __GNUC__
+    __attribute__((format(printf, 2, 3)))
+#endif
+    ;
+
+size_t gbs_totalmemused(gbs const str);
--- a/tool
+++ b/tool
@@ -308,7 +308,7 @@
       out_exe=cli
       ;;
     orca|tui)
-      add source_files osc_out.c term_util.c sysmisc.c tui_main.c
+      add source_files osc_out.c term_util.c sysmisc.c thirdparty/gbstring.c tui_main.c
       add cc_flags -D_XOPEN_SOURCE_EXTENDED=1
       # thirdparty headers (like sokol_time.h) should get -isystem for their
       # include dir so that any warnings they generate with our warning flags