1 #ifndef MSTRING_H
2 #define MSTRING_H
3 
4 #ifdef YARRAY_H
5 #error include yarray.h after mstring.h
6 #endif
7 
8 #include "ref.h"
9 #include <stdlib.h>
10 
11 /*
12  * A reference counted string buffer of arbitrary but fixed size.
13  */
14 class MStringData {
15 public:
MStringData()16     MStringData() : fRefCount(0) {}
17 
18     int fRefCount;
19     char fStr[];
20 };
21 
22 class MStringRef {
23 public:
MStringRef()24     MStringRef(): fStr(nullptr) {}
MStringRef(MStringData * data)25     explicit MStringRef(MStringData* data): fStr(data) {}
MStringRef(size_t len)26     explicit MStringRef(size_t len) { alloc(len); }
MStringRef(const char * str,size_t len)27     MStringRef(const char* str, size_t len) { create(str, len); }
28 
29     void alloc(size_t len);
30     void create(const char* str, size_t len);
31     operator bool() const { return fStr; }
32     MStringData* operator->() const { return fStr; }
33     bool operator!=(const MStringRef& r) const { return fStr != r.fStr; }
34     char& operator[](size_t index) const { return fStr->fStr[index]; }
35     void operator=(MStringData* data) { fStr = data; }
acquire()36     void acquire() const { fStr->fRefCount++; }
release()37     void release() const { if (fStr->fRefCount-- == 1) free(fStr); }
38 
39 private:
40 
41     MStringData* fStr;
42 };
43 
44 /*
45  * Mutable strings with a reference counted string buffer.
46  */
47 class mstring {
48 private:
49     friend class MStringArray;
50     friend mstring operator+(const char* s, const mstring& m);
51 
52     MStringRef fRef;
53     size_t fOffset;
54     size_t fCount;
55 
acquire()56     void acquire() {
57         if (fRef) { fRef.acquire(); }
58     }
release()59     void release() {
60         if (fRef) { fRef.release(); }
61     }
62     mstring(const MStringRef& str, size_t offset, size_t count);
63     mstring(const char* str1, size_t len1, const char* str2, size_t len2);
data()64     const char* data() const { return &fRef[fOffset]; }
65 
66 public:
67     mstring(const char *str);
68     mstring(const char *str1, const char *str2);
69     mstring(const char *str1, const char *str2, const char *str3);
70     mstring(const char *str1, const char *str2, const char *str3,
71             const char *str4, const char *str5 = nullptr,
72             const char *str6 = nullptr);
73     mstring(const char *str, size_t len);
74     explicit mstring(long);
75 
mstring(null_ref &)76     mstring(null_ref &): fRef(nullptr), fOffset(0), fCount(0) { }
mstring()77     mstring():           fRef(nullptr), fOffset(0), fCount(0) { }
78 
mstring(const mstring & r)79     mstring(const mstring &r):
80         fRef(r.fRef),
81         fOffset(r.fOffset),
82         fCount(r.fCount)
83     {
84         acquire();
85     }
~mstring()86     ~mstring() {
87         release();
88     }
89 
length()90     size_t length() const { return fCount; }
offset()91     size_t offset() const { return fOffset; }
isEmpty()92     bool isEmpty() const { return 0 == fCount; }
nonempty()93     bool nonempty() const { return 0 < fCount; }
94 
95     mstring& operator=(const mstring& rv);
96     void operator+=(const mstring& rv);
97     mstring operator+(const mstring& rv) const;
98 
99     bool operator==(const char *rv) const { return equals(rv); }
100     bool operator!=(const char *rv) const { return !equals(rv); }
101     bool operator==(const mstring &rv) const { return equals(rv); }
102     bool operator!=(const mstring &rv) const { return !equals(rv); }
103     bool operator==(null_ref &) const { return isEmpty(); }
104     bool operator!=(null_ref &) const { return nonempty(); }
105 
106     mstring operator=(null_ref &) { return *this = mstring(); }
107     mstring substring(size_t pos) const;
108     mstring substring(size_t pos, size_t len) const;
109     mstring match(const char* regex, const char* flags = nullptr) const;
110 
111     int operator[](int pos) const { return charAt(pos); }
112     int charAt(int pos) const;
113     int indexOf(char ch) const;
114     int lastIndexOf(char ch) const;
115     int count(char ch) const;
116 
117     bool equals(const char *s) const;
118     bool equals(const char *s, size_t len) const;
119     bool equals(const mstring &s) const;
120     int collate(mstring s, bool ignoreCase = false);
121     int compareTo(const mstring &s) const;
122     bool operator<(const mstring& other) const { return compareTo(other) < 0; }
123     bool copyTo(char *dst, size_t len) const;
124 
125     bool startsWith(const mstring &s) const;
126     bool endsWith(const mstring &s) const;
127     int find(const mstring &s) const;
128 
129     bool split(unsigned char token, mstring *left, mstring *remain) const;
130     bool splitall(unsigned char token, mstring *left, mstring *remain) const;
131     mstring trim() const;
132     mstring replace(int position, int len, const mstring &insert) const;
133     mstring remove(int position, int len) const;
134     mstring insert(int position, const mstring &s) const;
append(const mstring & str)135     mstring append(const mstring &str) const { return *this + str; }
136     mstring searchAndReplaceAll(const mstring& s, const mstring& r) const;
137     mstring lower() const;
138     mstring upper() const;
139 
140     operator const char *() { return c_str(); }
141     const char* c_str();
142 };
143 
144 inline bool operator==(const char* s, const mstring& c) { return c == s; }
145 inline bool operator!=(const char* s, const mstring& c) { return c != s; }
146 
147 inline mstring operator+(const char* s, const mstring& m) {
148     return mstring(s) + m;
149 }
150 
151 #endif
152 
153 // vim: set sw=4 ts=4 et:
154