URI: 
       ttxtbuf.c - ltk - Socket-based GUI for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ttxtbuf.c (3291B)
       ---
            1 #include <stdio.h>
            2 #include <stdlib.h>
            3 #include <string.h>
            4 #include <stdarg.h>
            5 
            6 #include "util.h"
            7 #include "memory.h"
            8 #include "txtbuf.h"
            9 #include "assert.h"
           10 
           11 txtbuf *
           12 txtbuf_new(void) {
           13         txtbuf *buf = ltk_malloc(sizeof(txtbuf));
           14         buf->text = NULL;
           15         buf->cap = buf->len = 0;
           16         return buf;
           17 }
           18 
           19 txtbuf *
           20 txtbuf_new_from_char(const char *str) {
           21         txtbuf *buf = ltk_malloc(sizeof(txtbuf));
           22         buf->text = ltk_strdup(str);
           23         buf->len = strlen(str);
           24         buf->cap = buf->len + 1;
           25         return buf;
           26 }
           27 
           28 txtbuf *
           29 txtbuf_new_from_char_len(const char *str, size_t len) {
           30         txtbuf *buf = ltk_malloc(sizeof(txtbuf));
           31         buf->text = ltk_strndup(str, len);
           32         buf->len = len;
           33         buf->cap = len + 1;
           34         return buf;
           35 }
           36 
           37 void
           38 txtbuf_fmt(txtbuf *buf, const char *fmt, ...) {
           39         va_list args;
           40         va_start(args, fmt);
           41         int len = vsnprintf(buf->text, buf->cap, fmt, args);
           42         /* FIXME: len can never be negative, right? */
           43         /* FIXME: maybe also shrink here */
           44         if ((size_t)len >= buf->cap) {
           45                 va_end(args);
           46                 va_start(args, fmt);
           47                 txtbuf_resize(buf, len);
           48                 vsnprintf(buf->text, buf->cap, fmt, args);
           49         }
           50         buf->len = len;
           51         va_end(args);
           52 }
           53 
           54 void
           55 txtbuf_set_text(txtbuf *buf, const char *text) {
           56         txtbuf_set_textn(buf, text, strlen(text));
           57 }
           58 
           59 void
           60 txtbuf_set_textn(txtbuf *buf, const char *text, size_t len) {
           61         txtbuf_resize(buf, len);
           62         buf->len = len;
           63         memmove(buf->text, text, len);
           64         buf->text[buf->len] = '\0';
           65 }
           66 
           67 void
           68 txtbuf_append(txtbuf *buf, const char *text) {
           69         txtbuf_appendn(buf, text, strlen(text));
           70 }
           71 
           72 /* FIXME: some sort of append that does not resize until there's not enough
           73    space so a buffer that will be filled up anyways doesn't have to be
           74    constantly resized */
           75 void
           76 txtbuf_appendn(txtbuf *buf, const char *text, size_t len) {
           77         /* FIXME: overflow protection here and everywhere else */
           78         txtbuf_resize(buf, buf->len + len);
           79         memmove(buf->text + buf->len, text, len);
           80         buf->len += len;
           81         buf->text[buf->len] = '\0';
           82 }
           83 
           84 void
           85 txtbuf_resize(txtbuf *buf, size_t sz) {
           86         /* always leave room for extra \0 */
           87         size_t cap = ideal_array_size(buf->cap, sz + 1);
           88         if (cap != buf->cap) {
           89                 buf->text = ltk_realloc(buf->text, cap);
           90                 buf->cap = cap;
           91         }
           92 }
           93 
           94 void
           95 txtbuf_destroy(txtbuf *buf) {
           96         if (!buf)
           97                 return;
           98         free(buf->text);
           99         free(buf);
          100 }
          101 
          102 void
          103 txtbuf_copy(txtbuf *dst, txtbuf *src) {
          104         txtbuf_resize(dst, src->len);
          105         if (src->text && dst->text) {
          106                 memcpy(dst->text, src->text, src->len);
          107                 dst->text[src->len] = '\0';
          108         }
          109         dst->len = src->len;
          110 }
          111 
          112 txtbuf *
          113 txtbuf_dup(txtbuf *src) {
          114         txtbuf *dst = txtbuf_new();
          115         txtbuf_copy(dst, src);
          116         return dst;
          117 }
          118 
          119 char *
          120 txtbuf_get_textcopy(txtbuf *buf) {
          121         return buf->text ? ltk_strndup(buf->text, buf->len) : ltk_strdup("");
          122 }
          123 
          124 /* FIXME: proper "normalize" function to add nul-termination if needed */
          125 int
          126 txtbuf_cmp(txtbuf *buf1, txtbuf *buf2) {
          127         /* FIXME: I guess strcmp would be possible as well since it's nul-terminated now */
          128         /* FIXME: Test this because I was tired while writing it */
          129         int cmp = strncmp(buf1->text, buf2->text, buf1->len < buf2->len ? buf1->len : buf2->len);
          130         if (cmp == 0) {
          131                 if (buf1->len < buf2->len)
          132                         return -1;
          133                 else if (buf1->len > buf2->len)
          134                         return 1;
          135         }
          136         return cmp;
          137 }
          138 
          139 int
          140 txtbuf_eql(txtbuf *buf1, txtbuf *buf2) {
          141         return txtbuf_cmp(buf1, buf2) == 0;
          142 }
          143 
          144 void
          145 txtbuf_clear(txtbuf *buf) {
          146         if (buf->len > 0) {
          147                 buf->len = 0;
          148                 buf->text[0] = '\0';
          149         }
          150 }