libostd/octa/string.h

186 lines
5.0 KiB
C
Raw Normal View History

2015-05-27 22:43:13 +02:00
/* String for OctaSTD.
*
* This file is part of OctaSTD. See COPYING.md for futher information.
*/
#ifndef OCTA_STRING_H
#define OCTA_STRING_H
2015-05-27 23:15:24 +02:00
#include <stdio.h>
2015-05-27 22:43:13 +02:00
#include <stddef.h>
#include "octa/utility.h"
#include "octa/range.h"
#include "octa/vector.h"
namespace octa {
static constexpr size_t npos = -1;
template<typename T>
class StringBase {
Vector<T> p_buf;
void terminate() {
if (p_buf.empty() || (p_buf.last() != '\0')) p_buf.push('\0');
}
public:
typedef size_t SizeType;
typedef ptrdiff_t DiffType;
typedef T ValType;
typedef T &RefType;
typedef const T &ConstRefType;
typedef T *PtrType;
typedef const T *ConstPtrType;
typedef PointerRange< T> RangeType;
typedef PointerRange<const T> ConstRangeType;
StringBase(): p_buf(1, '\0') {}
StringBase(const StringBase &s): p_buf(s.p_buf) {}
StringBase(StringBase &&s): p_buf(move(s.p_buf)) {}
StringBase(const StringBase &s, size_t pos, size_t len = npos):
p_buf(s.p_buf.each().slice(pos,
2015-05-28 00:19:16 +02:00
(len == npos) ? s.p_buf.size() : (pos + len))) {
2015-05-27 22:43:13 +02:00
terminate();
}
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
StringBase(const T *v): p_buf(PointerRange<const T>(v, strlen(v) + 1)) {}
template<typename R> StringBase(R range): p_buf(range) {
terminate();
}
void clear() { p_buf.clear(); }
StringBase<T> &operator=(const StringBase &v) {
p_buf.operator=(v);
return *this;
}
StringBase<T> &operator=(StringBase &&v) {
p_buf.operator=(move(v));
return *this;
}
StringBase<T> &operator=(const T *v) {
p_buf = PointerRange<const T>(v, strlen(v) + 1);
return *this;
}
T &operator[](size_t i) { return p_buf[i]; }
const T &operator[](size_t i) const { return p_buf[i]; }
T &at(size_t i) { return p_buf[i]; }
const T &at(size_t i) const { return p_buf[i]; }
T &first() { return p_buf[0]; }
const T &first() const { return p_buf[0]; };
2015-05-28 00:19:16 +02:00
T &last() { return p_buf[size() - 1]; }
const T &last() const { return p_buf[size() - 1]; }
2015-05-27 22:43:13 +02:00
T *data() { return p_buf.data(); }
const T *data() const { return p_buf.data(); }
2015-05-28 00:19:16 +02:00
size_t size() const {
return p_buf.size() - 1;
2015-05-27 22:43:13 +02:00
}
size_t capacity() const {
return p_buf.capacity() - 1;
}
2015-05-28 00:19:16 +02:00
bool empty() const { return (size() == 0); }
2015-05-27 22:43:13 +02:00
2015-05-27 23:15:24 +02:00
void push(T v) {
p_buf.last() = v;
p_buf.push('\0');
}
2015-05-27 22:43:13 +02:00
StringBase<T> &operator+=(const StringBase &s) {
p_buf.pop();
2015-05-28 00:19:16 +02:00
p_buf.insert_range(p_buf.size(), s.p_buf.each());
2015-05-27 22:43:13 +02:00
return *this;
}
StringBase<T> &operator+=(const T *s) {
p_buf.pop();
2015-05-28 00:19:16 +02:00
p_buf.insert_range(p_buf.size(), PointerRange<const T>(s,
2015-05-27 22:43:13 +02:00
strlen(s) + 1));
return *this;
}
StringBase<T> &operator+=(T c) {
p_buf.pop();
p_buf.push(c);
p_buf.push('\0');
return *this;
}
RangeType each() {
2015-05-28 00:19:16 +02:00
return PointerRange<T>(p_buf.data(), size());
2015-05-27 22:43:13 +02:00
}
ConstRangeType each() const {
2015-05-28 00:19:16 +02:00
return PointerRange<const T>(p_buf.data(), size());
2015-05-27 22:43:13 +02:00
}
void swap(StringBase &v) {
p_buf.swap(v);
}
};
typedef StringBase<char> String;
2015-05-27 23:05:51 +02:00
template<typename R, typename F>
2015-05-27 23:32:35 +02:00
String concat(R range, String sep, F func) {
String ret;
if (range.empty()) return move(ret);
for (;;) {
ret += func(range.first());
range.pop_first();
if (range.empty()) break;
ret += sep;
}
return move(ret);
}
2015-05-27 23:05:51 +02:00
template<typename R>
String concat(R range, String sep = " ") {
String ret;
if (range.empty()) return move(ret);
for (;;) {
ret += range.first();
range.pop_first();
if (range.empty()) break;
ret += sep;
}
return move(ret);
}
2015-05-27 23:15:24 +02:00
template<typename T> struct ToString {
typedef T ArgType;
typedef String ResultType;
String operator()(const T &) { return ""; }
};
2015-05-27 23:15:24 +02:00
template<> struct ToString<char> {
typedef char ArgType;
typedef String ResultType;
String operator()(char c) {
String ret;
ret.push(c);
return move(ret);
}
};
2015-05-27 23:15:24 +02:00
template<> struct ToString<int> {
typedef int ArgType;
typedef String ResultType;
String operator()(int v) {
char buf[128];
sprintf(buf, "%d", v);
return String((const char *)buf);
}
};
2015-05-27 22:43:13 +02:00
}
#endif