Last active
July 15, 2016 18:16
-
-
Save FlyingJester/bac0374f2332ce71243a08787baeb202 to your computer and use it in GitHub Desktop.
Lime String Implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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