2015-08-05 20:26:58 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015 Andrew Kelley
|
|
|
|
*
|
|
|
|
* This file is part of zig, which is MIT licensed.
|
|
|
|
* See http://opensource.org/licenses/MIT
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ZIG_BUFFER_HPP
|
|
|
|
#define ZIG_BUFFER_HPP
|
|
|
|
|
|
|
|
#include "list.hpp"
|
|
|
|
|
|
|
|
#include <assert.h>
|
2015-08-05 21:47:08 -07:00
|
|
|
#include <stdint.h>
|
2015-11-29 16:28:28 -08:00
|
|
|
#include <ctype.h>
|
2015-11-30 23:50:11 -08:00
|
|
|
#include <stdarg.h>
|
2015-08-05 20:26:58 -07:00
|
|
|
|
2015-11-24 14:01:37 -08:00
|
|
|
#define BUF_INIT {{0}}
|
|
|
|
|
2015-11-25 14:17:19 -08:00
|
|
|
// Note, you must call one of the alloc, init, or resize functions to have an
|
|
|
|
// initialized buffer. The assertions should help with this.
|
2015-08-05 20:26:58 -07:00
|
|
|
struct Buf {
|
|
|
|
ZigList<char> list;
|
|
|
|
};
|
|
|
|
|
2015-08-05 21:47:08 -07:00
|
|
|
Buf *buf_sprintf(const char *format, ...)
|
|
|
|
__attribute__ ((format (printf, 1, 2)));
|
2015-11-30 23:50:11 -08:00
|
|
|
Buf *buf_vprintf(const char *format, va_list ap);
|
2015-08-05 21:47:08 -07:00
|
|
|
|
2015-08-05 20:26:58 -07:00
|
|
|
static inline int buf_len(Buf *buf) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-05 20:26:58 -07:00
|
|
|
return buf->list.length - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline char *buf_ptr(Buf *buf) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-05 20:26:58 -07:00
|
|
|
return buf->list.items;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void buf_resize(Buf *buf, int new_len) {
|
|
|
|
buf->list.resize(new_len + 1);
|
|
|
|
buf->list.at(buf_len(buf)) = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Buf *buf_alloc(void) {
|
|
|
|
Buf *buf = allocate<Buf>(1);
|
|
|
|
buf_resize(buf, 0);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Buf *buf_alloc_fixed(int size) {
|
|
|
|
Buf *buf = allocate<Buf>(1);
|
|
|
|
buf_resize(buf, size);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void buf_deinit(Buf *buf) {
|
|
|
|
buf->list.deinit();
|
|
|
|
}
|
|
|
|
|
2015-11-03 21:31:27 -08:00
|
|
|
static inline void buf_init_from_mem(Buf *buf, const char *ptr, int len) {
|
2015-12-03 14:59:14 -08:00
|
|
|
assert(len >= 0);
|
2015-08-05 20:26:58 -07:00
|
|
|
buf->list.resize(len + 1);
|
|
|
|
memcpy(buf_ptr(buf), ptr, len);
|
|
|
|
buf->list.at(buf_len(buf)) = 0;
|
2015-11-02 02:39:36 -08:00
|
|
|
}
|
|
|
|
|
2015-11-06 21:11:47 -08:00
|
|
|
static inline void buf_init_from_str(Buf *buf, const char *str) {
|
|
|
|
buf_init_from_mem(buf, str, strlen(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void buf_init_from_buf(Buf *buf, Buf *other) {
|
|
|
|
buf_init_from_mem(buf, buf_ptr(other), buf_len(other));
|
|
|
|
}
|
|
|
|
|
2015-11-03 21:31:27 -08:00
|
|
|
static inline Buf *buf_create_from_mem(const char *ptr, int len) {
|
2015-12-03 14:59:14 -08:00
|
|
|
assert(len >= 0);
|
2015-11-02 02:39:36 -08:00
|
|
|
Buf *buf = allocate<Buf>(1);
|
|
|
|
buf_init_from_mem(buf, ptr, len);
|
2015-08-05 20:26:58 -07:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2015-11-03 21:31:27 -08:00
|
|
|
static inline Buf *buf_create_from_str(const char *str) {
|
2015-11-02 02:39:36 -08:00
|
|
|
return buf_create_from_mem(str, strlen(str));
|
2015-08-05 21:47:08 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 14:59:14 -08:00
|
|
|
static inline Buf *buf_create_from_buf(Buf *buf) {
|
|
|
|
return buf_create_from_mem(buf_ptr(buf), buf_len(buf));
|
|
|
|
}
|
|
|
|
|
2015-08-05 20:26:58 -07:00
|
|
|
static inline Buf *buf_slice(Buf *in_buf, int start, int end) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(in_buf->list.length);
|
2015-08-05 20:26:58 -07:00
|
|
|
assert(start >= 0);
|
|
|
|
assert(end >= 0);
|
|
|
|
assert(start < buf_len(in_buf));
|
|
|
|
assert(end <= buf_len(in_buf));
|
|
|
|
Buf *out_buf = allocate<Buf>(1);
|
|
|
|
out_buf->list.resize(end - start + 1);
|
|
|
|
memcpy(buf_ptr(out_buf), buf_ptr(in_buf) + start, end - start);
|
|
|
|
out_buf->list.at(buf_len(out_buf)) = 0;
|
|
|
|
return out_buf;
|
|
|
|
}
|
|
|
|
|
2015-08-23 22:45:20 -07:00
|
|
|
static inline void buf_append_mem(Buf *buf, const char *mem, int mem_len) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-23 22:45:20 -07:00
|
|
|
assert(mem_len >= 0);
|
2015-08-05 20:26:58 -07:00
|
|
|
int old_len = buf_len(buf);
|
2015-08-23 22:45:20 -07:00
|
|
|
buf_resize(buf, old_len + mem_len);
|
|
|
|
memcpy(buf_ptr(buf) + old_len, mem, mem_len);
|
2015-08-05 20:26:58 -07:00
|
|
|
buf->list.at(buf_len(buf)) = 0;
|
|
|
|
}
|
|
|
|
|
2015-08-23 22:45:20 -07:00
|
|
|
static inline void buf_append_str(Buf *buf, const char *str) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-23 22:45:20 -07:00
|
|
|
buf_append_mem(buf, str, strlen(str));
|
|
|
|
}
|
|
|
|
|
2015-08-05 20:26:58 -07:00
|
|
|
static inline void buf_append_buf(Buf *buf, Buf *append_buf) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-23 22:45:20 -07:00
|
|
|
buf_append_mem(buf, buf_ptr(append_buf), buf_len(append_buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void buf_append_char(Buf *buf, uint8_t c) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-23 22:45:20 -07:00
|
|
|
buf_append_mem(buf, (const char *)&c, 1);
|
|
|
|
}
|
|
|
|
|
2015-11-01 21:21:33 -08:00
|
|
|
void buf_appendf(Buf *buf, const char *format, ...)
|
|
|
|
__attribute__ ((format (printf, 2, 3)));
|
|
|
|
|
2015-08-23 22:45:20 -07:00
|
|
|
static inline bool buf_eql_mem(Buf *buf, const char *mem, int mem_len) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-23 22:45:20 -07:00
|
|
|
if (buf_len(buf) != mem_len)
|
|
|
|
return false;
|
|
|
|
return memcmp(buf_ptr(buf), mem, mem_len) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool buf_eql_str(Buf *buf, const char *str) {
|
2015-11-25 14:17:19 -08:00
|
|
|
assert(buf->list.length);
|
2015-08-23 22:45:20 -07:00
|
|
|
return buf_eql_mem(buf, str, strlen(str));
|
|
|
|
}
|
|
|
|
|
2016-05-07 01:58:18 -07:00
|
|
|
static inline bool buf_starts_with_mem(Buf *buf, const char *mem, int mem_len) {
|
|
|
|
if (buf_len(buf) < mem_len) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return memcmp(buf_ptr(buf), mem, mem_len) == 0;
|
|
|
|
}
|
|
|
|
|
2016-01-28 10:03:44 -08:00
|
|
|
static inline bool buf_starts_with_buf(Buf *buf, Buf *sub) {
|
2016-05-07 01:58:18 -07:00
|
|
|
return buf_starts_with_mem(buf, buf_ptr(sub), buf_len(sub));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool buf_starts_with_str(Buf *buf, const char *str) {
|
|
|
|
return buf_starts_with_mem(buf, str, strlen(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool buf_ends_with_mem(Buf *buf, const char *mem, int mem_len) {
|
|
|
|
if (buf_len(buf) < mem_len) {
|
2016-01-28 10:03:44 -08:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-07 01:58:18 -07:00
|
|
|
return memcmp(buf_ptr(buf) + buf_len(buf) - mem_len, mem, mem_len) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool buf_ends_with_str(Buf *buf, const char *str) {
|
|
|
|
return buf_ends_with_mem(buf, str, strlen(str));
|
2016-01-28 10:03:44 -08:00
|
|
|
}
|
|
|
|
|
2015-11-30 08:14:58 -08:00
|
|
|
bool buf_eql_buf(Buf *buf, Buf *other);
|
|
|
|
uint32_t buf_hash(Buf *buf);
|
2015-08-05 21:47:08 -07:00
|
|
|
|
2015-11-29 16:28:28 -08:00
|
|
|
static inline void buf_upcase(Buf *buf) {
|
|
|
|
for (int i = 0; i < buf_len(buf); i += 1) {
|
|
|
|
buf_ptr(buf)[i] = toupper(buf_ptr(buf)[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-05 20:26:58 -07:00
|
|
|
#endif
|