1#include "DString.h"
2
3#include <string.h>
4
5using namespace Udf;
6
7/*! \brief Creates a useless, empty string object.
8*/
9DString::DString()
10	: fString(NULL)
11	, fLength(0)
12{
13}
14
15/*! \brief Create a new DString object that is a copy of \a ref.
16*/
17DString::DString(const DString &ref)
18	: fString(NULL)
19	, fLength(0)
20{
21	SetTo(ref);
22}
23
24/*! \brief Creates a new DString \a fieldLength bytes long that contains
25	at most the first \c (fieldLength-1) bytes of \a string.Cs0().
26*/
27DString::DString(const Udf::String &string, uint8 fieldLength)
28	: fString(NULL)
29	, fLength(0)
30{
31	SetTo(string, fieldLength);
32}
33
34/*! \brief Creates a new DString \a fieldLength bytes long that contains
35	at most the first \c (fieldLength-1) bytes of the Cs0 representation
36	of the NULL-terminated UTF8 string \a utf8.
37*/
38DString::DString(const char *utf8, uint8 fieldLength)
39	: fString(NULL)
40	, fLength(0)
41{
42	SetTo(utf8, fieldLength);
43}
44
45void
46DString::SetTo(const DString &ref)
47{
48	_Clear();
49	if (ref.Length() > 0) {
50		fString = new(nothrow) uint8[ref.Length()];
51		if (fString) {
52			fLength = ref.Length();
53			memcpy(fString, ref.String(), fLength);
54		}
55	}
56}
57
58/*! \brief Sets the DString be \a fieldLength bytes long and contain
59	at most the first \c (fieldLength-1) bytes of \a string.Cs0().
60*/
61void
62DString::SetTo(const Udf::String &string, uint8 fieldLength)
63{
64	_Clear();
65	if (fieldLength > 0) {
66		// Allocate our string
67		fString = new(nothrow) uint8[fieldLength];
68		status_t error = fString ? B_OK : B_NO_MEMORY;
69		if (!error) {
70			// Figure out how many bytes to copy
71			uint32 sourceLength = string.Cs0Length();
72			if (sourceLength > 0) {
73				uint8 destLength = sourceLength > uint8(fieldLength-1)
74				                   ? uint8(fieldLength-1)
75				                   : uint8(sourceLength);
76				// If the source string is 16-bit unicode, make sure any dangling
77				// half-character at the end of the string is not copied
78				if (string.Cs0()[1] == '\x10' && destLength > 0 && destLength % 2 == 0)
79					destLength--;
80				// Copy
81				memcpy(fString, string.Cs0(), destLength);
82				// Zero any characters between the end of the string and
83				// the terminating string length character
84				if (destLength < fieldLength-1)
85					memset(&fString[destLength], 0, fieldLength-1-destLength);
86				// Write the string length to the last character in the field
87				fString[fieldLength-1] = destLength;
88			} else {
89				// Empty strings are to contain all zeros
90				memset(fString, 0, fieldLength);
91			}
92		}
93	}
94}
95
96/*! \brief Sets the DString be \a fieldLength bytes long and contain
97	at most the first \c (fieldLength-1) bytes of the Cs0 representation
98	of the NULL-terminated UTF8 string \a utf8.
99*/
100void
101DString::SetTo(const char *utf8, uint8 fieldLength)
102{
103	Udf::String string(utf8);
104	SetTo(string, fieldLength);
105}
106
107void
108DString::_Clear()
109{
110	DEBUG_INIT("DString");
111	delete [] fString;
112	fString = NULL;
113	fLength = 0;
114}
115