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