summaryrefslogtreecommitdiffhomepage
path: root/docs/cstr_api.md
blob: cd827dc628f70df0e4f6b86188ac21f51ea8d3c1 (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# STC [cstr](../include/stc/cstr.h): String
![String](pics/string.jpg)

A **cstr** object represent sequences of characters. It supports an interface similar to that of a standard container of bytes, but adding features specifically designed to operate with strings of single-byte characters, terminated by the null character.

See the c++ class [std::basic_string](https://en.cppreference.com/w/cpp/string/basic_string) for a functional description.

## Header file

All cstr definitions and prototypes are available by including a single header file.

```c
#define i_implement // define this (or use global STC_IMPLEMENT) in one source file only!
#include <stc/cstr.h>
```
## Methods

```c
cstr         cstr_init(void);                                         // constructor; same as cstr_null.
cstr         cstr_new(const char literal_only[]);                     // cstr from literal; no strlen() call.
cstr         cstr_from(const char* str);                              // constructor using strlen()
cstr         cstr_from_n(const char* str, size_t n);                  // constructor with specified length
cstr         cstr_with_capacity(size_t cap);
cstr         cstr_with_size(size_t len, char fill);                   // repeat fill len times
cstr         cstr_from_fmt(const char* fmt, ...);                     // printf() formatting
cstr         cstr_clone(cstr s);

cstr*        cstr_take(cstr* self, cstr s);                           // take the constructed or moved string
cstr         cstr_move(cstr* self);                                   // move string to caller, leave empty string
void         cstr_drop(cstr *self);                                   // destructor

const char*  cstr_str(const cstr* self);                              // access to const char*
char*        cstr_data(cstr* self);                                   // access to char*
csview       cstr_sv(const cstr* self);                               // access to string view
cstr_buf     cstr_buffer(cstr* self);                                 // access to mutable buffer (with capacity)

size_t       cstr_size(cstr s);
size_t       cstr_length(cstr s);
size_t       cstr_capacity(cstr s);
bool         cstr_empty(cstr s);

// utf8 encoded strings: 
size_t       cstr_size_u8(cstr s);                                    // number of utf8 codepoints
size_t       cstr_size_n_u8(cstr s, size_t nbytes);                   // utf8 size within n bytes  
csview       cstr_at(const cstr* self, size_t bytepos);               // utf8 codepoints as a csview
csview       cstr_at_u8(const cstr* self, size_t u8idx);              // utf8 codepoints at utf8 pos
size_t       cstr_pos_u8(const cstr* self, size_t u8idx);             // byte position at utf8 index
// utf8 functions requires linking with src/utf8code.c:
bool         cstr_valid_u8(const cstr* self);                         // check if str is valid utf8
cstr         cstr_tolower(const cstr* self);                          // returns new lowercase utf8 cstr
cstr         cstr_toupper(const cstr* self);                          // returns new uppercase utf8 cstr
void         cstr_lowercase(cstr* self);                              // transform cstr to lowercase utf8
void         cstr_uppercase(cstr* self);                              // transform cstr to uppercase utf8
bool         cstr_iequals(cstr s, const char* str);                   // case-insensitive comparison
bool         cstr_istarts_with(cstr s, const char* str);              //   "
bool         cstr_iends_with(cstr s, const char* str);                //   "
int          cstr_icmp(const cstr* s1, const cstr* s2);               //   "

size_t       cstr_reserve(cstr* self, size_t capacity);
void         cstr_resize(cstr* self, size_t len, char fill);
void         cstr_shrink_to_fit(cstr* self);
char*        cstr_expand_uninit(cstr* self, size_t n);                // return ptr to uninit data
void         cstr_clear(cstr* self);

char*        cstr_assign(cstr* self, const char* str);
char*        cstr_assign_s(cstr* self, cstr s);
char*        cstr_assign_n(cstr* self, const char* str, size_t n);    // assign n first chars of str
void         cstr_copy(cstr* self, cstr s);                           // like cstr_assign_s()
int          cstr_printf(cstr* self, const char* fmt, ...);           // printf() formatting

char*        cstr_append(cstr* self, const char* app);
char*        cstr_append_s(cstr* self, cstr app);
char*        cstr_append_n(cstr* self, const char* app, size_t n);

void         cstr_insert(cstr* self, size_t pos, const char* ins);
void         cstr_insert_s(cstr* self, size_t pos, cstr ins);
void         cstr_insert_n(cstr* self, size_t pos, const char* ins, size_t n);

void         cstr_replace(cstr* self, size_t pos, size_t len, const char* repl);
void         cstr_replace_s(cstr* self, size_t pos, size_t len, cstr repl);
void         cstr_replace_n(cstr* self, size_t pos, size_t len, const char* repl, size_t n);
size_t       cstr_replace_one(cstr* self, size_t startpos, const char* search, const char* repl);
void         cstr_replace_all(cstr* self, const char* search, const char* repl);

void         cstr_erase(cstr* self, size_t pos);
void         cstr_erase_n(cstr* self, size_t pos, size_t n);

bool         cstr_equals(cstr s, const char* str);
bool         cstr_equals_s(cstr s, cstr s2);
size_t       cstr_find(cstr s, const char* search);
size_t       cstr_find_from(cstr s, size_t pos, const char* search);
bool         cstr_contains(cstr s, const char* search);
bool         cstr_starts_with(cstr s, const char* str);
bool         cstr_ends_with(cstr s, const char* str);

void         cstr_push_back(cstr* self, char ch);
void         cstr_pop_back(cstr* self);
char*        cstr_front(cstr* self);
char*        cstr_back(cstr* self);

bool         cstr_getline(cstr *self, FILE *stream);                  // cstr_getdelim(self, '\n', stream)
bool         cstr_getdelim(cstr *self, int delim, FILE *stream);      // does not append delim to result
```

Note that all methods with arguments `(..., const char* str, size_t n)`, `n` must be within the range of `str` length.

#### Helper methods:
```c
int          cstr_cmp(const cstr *s1, const cstr *s2);
bool         cstr_eq(const cstr *s1, const cstr *s2);
bool         cstr_hash(const cstr *s);

char*        c_strnstrn(const char* str, const char* search, size_t slen, size_t nlen);
int          c_strncasecmp(const char* str1, const char* str2, size_t n);
```

## Types

| Type name       | Type definition                            | Used to represent... |
|:----------------|:-------------------------------------------|:---------------------|
| `cstr`          | `struct { ... }`                           | The string type      |
| `cstr_value`    | `char`                                     | String element type  |
| `csview`        | `struct { const char *str; size_t size; }` | String view type     |
| `cstr_buf`      | `struct { char *data; size_t size, cap; }` | String buffer type   |

## Constants and macros

| Name              | Value             |
|:------------------|:------------------|
|  `cstr_npos`      | `INTPTR_MAX`      |
|  `cstr_null`      | cstr null value   |

## Example
```c
#define i_implement
#include <stc/cstr.h>

int main() {
    cstr s0 = cstr_new("Initialization without using strlen().");
    printf("%s\nLength: %" PRIuMAX "\n\n", cstr_str(&s0), cstr_size(s0));

    cstr s1 = cstr_new("one-nine-three-seven-five.");
    printf("%s\n", cstr_str(&s1));

    cstr_insert(&s1, 3, "-two");
    printf("%s\n", cstr_str(&s1));

    cstr_erase_n(&s1, 7, 5); // -nine
    printf("%s\n", cstr_str(&s1));

    cstr_replace(&s1, cstr_find(s1, "seven"), 5, "four");
    printf("%s\n", cstr_str(&s1));

    // reassign:
    cstr_assign(&s1, "one two three four five six seven");
    cstr_append(&s1, " eight");
    printf("append: %s\n", cstr_str(&s1));

    cstr full_path = cstr_from_fmt("%s/%s.%s", "directory", "filename", "ext");
    printf("%s\n", cstr_str(&full_path));

    c_drop(cstr, &s0, &s1, &full_path);
}
```
Output:
```
one-nine-three-seven-five.
one-two-nine-three-seven-five.
one-two-three-seven-five.
one-two-three-four-five.
append: one two three four five six seven eight
directory/filename.ext
```