Skip to content

Instantly share code, notes, and snippets.

@FlyingJester
Last active July 15, 2016 18:16
Show Gist options
  • Save FlyingJester/bac0374f2332ce71243a08787baeb202 to your computer and use it in GitHub Desktop.
Save FlyingJester/bac0374f2332ce71243a08787baeb202 to your computer and use it in GitHub Desktop.
Lime String Implementation
#include "lime_string.hpp"
#if ! (defined LIME_STRING_NEW && defined LIME_STRING_DELETE)
#include <cstdlib>
#endif
namespace Lime{
#ifndef LIME_STRING_NEW
#define LIME_STRING_NEW malloc
#endif
#ifndef LIME_STRING_DELETE
#define LIME_STRING_DELETE free
#endif
void *String::newImpl(size_t size) {
return LIME_STRING_NEW(size);
}
void String::deleteImpl(void *p) {
return LIME_STRING_DELETE(p);
}
String::~String(){
if(m_capacity)
LIME_STRING_DELETE(m_data);
}
bool String::startsWith(const String &other, size_t start, size_t count) const{
const_iterator us = cbegin(), them = other.cbegin() + start;
const const_iterator them_end = them + count;
while(them != them_end){
if(*us != *them)
return false;
us++;
them++;
}
return true;
}
bool String::startsWith(const char *other, size_t start, size_t count) const {
const_iterator us = cbegin();
size_t i = start;
while(i < count){
if(other[i] != *us)
return false;
i++;
us++;
}
return true;
}
bool String::endsWith(const String &other, size_t start, size_t count) const {
const_iterator us = cend() - count, them = other.cbegin() + start;
const const_iterator them_end = them + count;
while(them != them_end){
if(*us != *them)
return false;
us++;
them++;
}
return false;
}
bool String::endsWith(const char *other, size_t start, size_t count) const {
const_reverse_iterator us = crend();
size_t i = start + count;
while(i-- != start){
if(*us != other[i])
return false;
us++;
}
return true;
}
void String::assign(const char *other, size_t start, size_t count){
if(m_capacity < count){
LIME_STRING_DELETE(m_data);
m_data = (char*)LIME_STRING_NEW(count);
m_capacity = count;
}
m_length = count;
for(size_t i = 0; i < count; i++){
m_data[i] = other[i + start];
}
}
// Assigns this string to be `count` copies of `character`. For instance,
// String::assign(3, 'z') would set the string to 'zzz'.
void String::assign(size_t count, char character){
if(m_capacity < count){
LIME_STRING_DELETE(m_data);
m_data = (char *)LIME_STRING_NEW(count);
m_capacity = count;
}
m_length = count;
for(size_t i = 0; i < count; i++){
m_data[i] = character;
}
}
char &String::operator[] (size_t position){
return m_data[position];
}
char String::operator[] (size_t position) const{
return m_data[position];
}
char &String::front(){ return *m_data; }
char String::front() const { return *m_data; }
char &String::back() { return m_data[m_length - 1]; }
char String::back() const { return m_data[m_length - 1]; }
const char *String::c_str() const { return m_data; }
void String::resize(size_t s, char character){
reserve(s);
while(m_length < s){
m_data[m_length++] = character;
}
}
void String::reserve(size_t s){
if(m_capacity < s){
char *new_data = (char *)LIME_STRING_NEW(s);
for(size_t i = 0; i < m_length; i++){
new_data[i] = m_data[i];
}
LIME_STRING_DELETE(m_data);
m_data = new_data;
m_capacity = s;
}
}
bool String::empty() const{
return m_length == 0;
}
size_t String::size() const{
return m_length;
}
size_t String::capacity() const{
return m_capacity;
}
void String::clear(bool freemem){
m_length = 0;
if(freemem){
m_capacity = false;
LIME_STRING_DELETE(m_data);
}
}
} // namespace Lime
#pragma once
#include <stdint.h>
namespace Lime {
class String {
public:
// These are used in self-hosting environments.
static void *newImpl(size_t size);
static void deleteImpl(void *p);
static void *operator new(size_t size) { return newImpl(size); }
static void operator delete(void *p) { return deleteImpl(p); }
static size_t StringLength(const char *that);
String();
template<typename T>
String(const T &other)
: m_length(0)
, m_capacity(0){
assign(other);
}
~String();
template<typename T>
struct strAdder {
static T *op(T *a, size_t b = 1){ return a + b; }
static T *rop(T *a, size_t b = 1){ return a - b; }
};
template<typename T>
struct strSubber {
static T *op(T *a, size_t b = 1){ return a - b; }
static T *rop(T *a, size_t b = 1){ return a + b; }
};
template<typename T, class Mover>
struct iteratorN {
friend class String;
static void *operator new(size_t size){ return String::newImpl(size); }
static void operator delete(void *p){ String::deleteImpl(p); }
iteratorN<T, Mover> &operator++(){
m_guts = Mover::op(m_guts);
return *this;
}
iteratorN<T, Mover> operator++(int i){
if(i){}
const T *old_guts = m_guts;
m_guts = Mover::op(m_guts);
return iteratorN(old_guts);
}
iteratorN<T, Mover> &operator--(){
m_guts = Mover::rop(m_guts);
return *this;
}
iteratorN<T, Mover> operator--(int i){
if(i){}
const T *old_guts = m_guts;
m_guts = Mover::rop(m_guts);
return iteratorN(old_guts);
}
iteratorN<T, Mover> &operator+=(size_t i){
m_guts = Mover::op(m_guts, i);
return *this;
}
iteratorN<T, Mover> &operator-=(size_t i){
m_guts = Mover::rop(m_guts, i);
return *this;
}
iteratorN<T, Mover> &operator=(const iteratorN<T, Mover> &other) {
m_guts = other.m_guts;
return *this;
}
iteratorN<T, Mover> operator+(size_t i) const{ return iteratorN(Mover::op(m_guts, i)); }
iteratorN<T, Mover> operator-(size_t i) const{ return iteratorN(Mover::rop(m_guts, i)); }
bool operator==(const iteratorN<T, Mover> &other) const{ return other.m_guts == m_guts; }
bool operator!=(const iteratorN<T, Mover> &other) const{ return other.m_guts != m_guts; }
bool operator<=(const iteratorN<T, Mover> &other) const{ return other.m_guts <= m_guts; }
bool operator>=(const iteratorN<T, Mover> &other) const{ return other.m_guts >= m_guts; }
bool operator<(const iteratorN<T, Mover> &other) const{ return other.m_guts < m_guts; }
bool operator>(const iteratorN<T, Mover> &other) const{ return other.m_guts > m_guts; }
T &operator*() { return *m_guts; }
iteratorN<T, strAdder<T> > base() const { return iteratorN<T, strAdder>(m_guts); }
private:
iteratorN(T *that)
: m_guts(that) {}
T *m_guts;
};
typedef iteratorN<char, strAdder<char> > iterator;
typedef iteratorN<const char, strAdder<const char> > const_iterator;
typedef iteratorN<char, strSubber<char> > reverse_iterator;
typedef iteratorN<const char, strSubber<const char> > const_reverse_iterator;
inline bool startsWith(const String &other, size_t start = 0) const {
return startsWith(other, start, other.m_length - start);
}
bool startsWith(const String &other, size_t start, size_t count) const;
bool startsWith(const char *other, size_t start = 0) const{
return startsWith(other, start, StringLength(other) - start);
}
bool startsWith(const char *other, size_t start, size_t count) const;
inline bool endsWith(const String &other, size_t start = 0) const {
return endsWith(other, start, other.m_length - start);
}
bool endsWith(const String &other, size_t start, size_t count) const;
bool endsWith(const char *other, size_t start = 0) const{
return endsWith(other, start, StringLength(other) - start);
}
bool endsWith(const char *other, size_t start, size_t count) const;
void assign(const String &other, size_t start = 0){
assign(other, start, other.m_length - start);
}
void assign(const String &other, size_t start, size_t count){
assign(other.m_data, start, count);
}
inline void assign(const char *other, size_t start = 0){
assign(other, start, StringLength(other) - start);
}
void assign(const char *other, size_t start, size_t count);
// Assigns this string to be `count` copies of `character`. For instance,
// String::assign(3, 'z') would set the string to 'zzz'.
void assign(size_t count, char character);
char &operator[] (size_t position);
char operator[] (size_t position) const;
char &front();
char front() const;
char &back();
char back() const;
const char *c_str() const;
inline const char *data() const { return c_str(); }
inline String &operator= (const String &other) { assign(other); return *this; }
inline String &operator= (const char *other) { assign(other); return *this; }
void resize(size_t s, char character);
void reserve(size_t s);
bool empty() const;
size_t size() const;
inline size_t length() const { return size(); }
size_t capacity() const;
void clear(bool freemem = false);
inline iterator begin() { return iterator(m_data); }
inline const_iterator begin() const { return cbegin(); }
inline const_iterator cbegin() const { return const_iterator(m_data); }
inline iterator end() { return iterator(m_data + m_length); }
inline const_iterator end() const { return cend(); }
inline const_iterator cend() const { return const_iterator(m_data + m_length); }
inline reverse_iterator rbegin() { return reverse_iterator(m_data + m_length - 1); }
inline const_reverse_iterator rbegin() const { return crbegin(); }
inline const_reverse_iterator crbegin() const { return const_reverse_iterator(m_data + m_length - 1); }
inline reverse_iterator rend() { return reverse_iterator(m_data - 1); }
inline const_reverse_iterator rend() const { return crend(); }
inline const_reverse_iterator crend() const { return const_reverse_iterator(m_data - 1); }
private:
char *m_data;
size_t m_capacity, m_length;
};
} // namespace Lime
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment