summaryrefslogtreecommitdiff
path: root/src/bin/sb.c
blob: a0dd9e855e9551ff97054ada149005c6cec051ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "private.h"
#include "sb.h"

#include <stdlib.h>
#include <stddef.h>
#include <string.h>

int
ty_sb_add(struct ty_sb *sb, const char *s, size_t len)
{
   size_t new_len = sb->len + len;

   if ((new_len + sb->gap >= sb->alloc) || !sb->buf)
     {
        size_t new_alloc = ((new_len + sb->gap + 15) / 16) * 24;
        char *new_buf;

        new_buf = realloc(sb->buf - sb->gap, new_alloc);
        if (new_buf == NULL)
          return -1;
        sb->buf = new_buf + sb->gap;
        sb->alloc = new_alloc;
     }
   memcpy(sb->buf + sb->len, s, len);
   sb->len += len;
   sb->buf[sb->len] = '\0';
   return 0;
}

int
ty_sb_prepend(struct ty_sb *sb, const char *s, size_t  len)
{
   if (len >= sb->gap)
     {
        size_t aligned_gap = ((len + 15) / 16) * 24;
        size_t third_of_alloc = (((sb->alloc / 3) + 15) / 16) * 16;
        size_t new_gap = MAX(aligned_gap, third_of_alloc);
        size_t new_alloc = sb->alloc + new_gap;
        char *new_buf;

        new_buf = calloc(new_alloc, 1);
        if (new_buf == NULL)
          return -1;

        memcpy(new_buf + new_gap, sb->buf, sb->len);
        free(sb->buf - sb->gap);
        sb->buf = new_buf + new_gap;
        sb->gap = new_gap;
        sb->alloc = new_alloc;
     }

   sb->buf -= len;
   sb->gap -= len;
   sb->len += len;
   memcpy(sb->buf, s, len);
   return 0;
}


/* unlike eina_strbuf_rtrim, only trims \t, \f, ' ' */
void
ty_sb_spaces_rtrim(struct ty_sb *sb)
{
   if (!sb->buf)
     return;

   while (sb->len > 0)
     {
        char c = sb->buf[sb->len - 1];
        if ((c != ' ') && (c != '\t') && (c != '\f'))
            break;
        sb->len--;
     }
   sb->buf[sb->len] = '\0';
}

char *
ty_sb_steal_buf(struct ty_sb *sb)
{
   size_t i;
   char *buf;

   if (!sb->len)
     return NULL;

   if (sb->gap != 0)
     {
        sb->buf -= sb->gap;
        for (i = 0; i <= sb->len; i++)
          {
             sb->buf[i] = sb->buf[i + sb->gap];
          }
        sb->gap = 0;
     }

   sb->alloc = 0;
   sb->gap = 0;
   sb->len = 0;

   buf = sb->buf;

   sb->buf = NULL;

   return buf;
}

void
ty_sb_lskip(struct ty_sb *sb, int len)
{
   sb->len -= len;
   sb->gap += len;
   sb->buf += len;
}

void
ty_sb_rskip(struct ty_sb *sb, int len)
{
   sb->len -= len;
   sb->buf[sb->len] = '\0';
}

void
ty_sb_free(struct ty_sb *sb)
{
   free(sb->buf - sb->gap);
   sb->gap = sb->len = sb->alloc = 0;
   sb->buf = NULL;
}