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