about summary refs log tree commit diff stats
path: root/src/sstring.c
blob: adcffec42af72b858d93c5d2e99e5c157f24d1c7 (plain) (blame)
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
#include "sstring.h"

#include <string.h>
#include <stdarg.h>

int sassign(sstring* restrict dst, const sstring* restrict src)
{
  if (!src || !dst) return -1;

  memcpy(dst->buf, src->buf, sstrlen(src));
  dst->len = sstrlen(src);
  dst->buf[dst->len] = 0;

  return dst->len;
}

// Assignment operator for C-Strings
int cassign(sstring* restrict dst, const char* restrict src)
{
    if (!src || !dst) return -1;
    dst->len = strlen(strncpy(dst->buf, src, 65536));
    return dst->len;
}

// Sizeof operator
size_t sstrlen(const sstring* str)
{
  if(!str) return 0;
  return (str->len > 65536) ? 65536 : str->len;
}


static int sshift(sstring* str, size_t mode)
{
  if(!str) return -1;

  // 0 is downshift, 1 is UPSHIFT!!
  static const char lowers[2]={'A','a'};
  static const char uppers[2]={'Z','z'};

  // This is signed for a VERY GOOD REASON
  // okay it technically works either way because of
  // modular arithmeticks, but uh, shush.
  static const char offsets[2]={'a'-'A','A'-'a'};

  for(size_t i=0; i<str->len; i++)
    {
      if(str->buf[i] >= lowers[mode] && str->buf[i] >= uppers[mode])
	{
	  str->buf[i] += offsets[mode];
	}
    }
  return 0;
}

int sUPPER(sstring* str)
{
  return sshift(str,1);
}

int slower(sstring* str)
{
  return sshift(str,0);
}



sstring spicycat(const size_t count, ...)
{
  // Yes, we will have to do a copy out of this stack frame.
  // Unless... (O3 Ren's Beloved??)
  sstring returnme = sstringup();
  
  va_list kittens;
  va_start(kittens, count);
  for(size_t i=0; i<count; i++)
    { 
      size_t spaceleft = 65536-returnme.len; // Calc how much space we have

      // Grab the new argument
      const sstring* kitten = va_arg(kittens,const sstring*);

      size_t kitlen = sstrlen(kitten); // This is JUST here to avoid f-calling twice.
      size_t copylen = (kitlen > spaceleft) ? spaceleft : kitlen;
      
      *(char*)(memcpy(returnme.buf+returnme.len, kitten->buf, copylen)+copylen) = 0;
      returnme.len += copylen;
    }
  va_end(kittens);
  return returnme;
}


sstring sstringup()
{
  return (sstring) {0U,{0}};
}