1// String.h
2
3#ifndef STRING_H
4#define STRING_H
5
6#include <SupportDefs.h>
7#include <string.h>
8#include <new>
9
10
11// string_hash
12//
13// from the Dragon Book: a slightly modified hashpjw()
14static inline
15uint32
16string_hash(const char *name)
17{
18	uint32 h = 0;
19	if (name) {
20		for (; *name; name++) {
21			uint32 g = h & 0xf0000000;
22			if (g)
23				h ^= g >> 24;
24			h = (h << 4) + *name;
25		}
26	}
27	return h;
28}
29
30#ifdef __cplusplus
31
32// String
33class String {
34public:
35	inline String();
36	inline String(const String &string);
37	inline String(const char *string, int32 length = -1);
38	inline ~String();
39
40	inline bool SetTo(const char *string, int32 maxLength = -1);
41	inline void Unset();
42
43	inline void Truncate(int32 newLength);
44
45	inline const char *GetString() const;
46	inline int32 GetLength() const	{ return fLength; }
47
48	inline uint32 GetHashCode() const	{ return string_hash(GetString()); }
49
50	inline String &operator=(const String &string);
51	inline bool operator==(const String &string) const;
52	inline bool operator!=(const String &string) const { return !(*this == string); }
53
54private:
55	inline bool _SetTo(const char *string, int32 length);
56
57private:
58	int32	fLength;
59	char	*fString;
60};
61
62// strnlen
63size_t
64strnlen(const char *str, size_t maxLen)
65{
66	if (str) {
67		size_t origMaxLen = maxLen;
68		while (maxLen > 0 && *str != '\0') {
69			maxLen--;
70			str++;
71		}
72		return origMaxLen - maxLen;
73	}
74	return 0;
75}
76
77
78/*!
79	\class String
80	\brief A very simple string class.
81*/
82
83// constructor
84String::String()
85	: fLength(0),
86	  fString(NULL)
87{
88}
89
90// copy constructor
91String::String(const String &string)
92	: fLength(0),
93	  fString(NULL)
94{
95	*this = string;
96}
97
98// constructor
99String::String(const char *string, int32 length)
100	: fLength(0),
101	  fString(NULL)
102{
103	SetTo(string, length);
104}
105
106// destructor
107String::~String()
108{
109	Unset();
110}
111
112// SetTo
113bool
114String::SetTo(const char *string, int32 maxLength)
115{
116	if (string) {
117		if (maxLength > 0)
118			maxLength = strnlen(string, maxLength);
119		else if (maxLength < 0)
120			maxLength = strlen(string);
121	}
122	return _SetTo(string, maxLength);
123}
124
125// Unset
126void
127String::Unset()
128{
129	if (fString) {
130		delete[] fString;
131		fString = NULL;
132	}
133	fLength = 0;
134}
135
136// Truncate
137void
138String::Truncate(int32 newLength)
139{
140	if (newLength < 0)
141		newLength = 0;
142	if (newLength < fLength) {
143		char *string = fString;
144		int32 len = fLength;
145		fString = NULL;
146		len = 0;
147		if (!_SetTo(string, newLength)) {
148			fString = string;
149			fLength = newLength;
150			fString[fLength] = '\0';
151		} else
152			delete[] string;
153	}
154}
155
156// GetString
157const char *
158String::GetString() const
159{
160	if (fString)
161		return fString;
162	return "";
163}
164
165// =
166String &
167String::operator=(const String &string)
168{
169	if (&string != this)
170		_SetTo(string.fString, string.fLength);
171	return *this;
172}
173
174// ==
175bool
176String::operator==(const String &string) const
177{
178	return (fLength == string.fLength
179			&& (fLength == 0 || !strcmp(fString, string.fString)));
180}
181
182// _SetTo
183bool
184String::_SetTo(const char *string, int32 length)
185{
186	bool result = true;
187	Unset();
188	if (string && length > 0) {
189		fString = new(std::nothrow) char[length + 1];
190		if (fString) {
191			memcpy(fString, string, length);
192			fString[length] = '\0';
193			fLength = length;
194		} else
195			result = false;
196	}
197	return result;
198}
199
200
201#endif	// __cplusplus
202
203#endif	// STRING_H
204