xref: /haiku/src/kits/debugger/value/value_formatters/IntegerValueFormatter.cpp (revision 2897df967633aab846ff4917b53e2af7d1e54eeb)
1 /*
2  * Copyright 2015, Rene Gollent, rene@gollent.com.
3  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Distributed under the terms of the MIT License.
5  */
6 #include "IntegerValueFormatter.h"
7 
8 #include <new>
9 
10 #include <ctype.h>
11 
12 #include "IntegerFormatter.h"
13 #include "IntegerValue.h"
14 
15 
16 // #pragma mark - IntegerValueFormatter
17 
18 
19 IntegerValueFormatter::IntegerValueFormatter(Config* config)
20 	:
21 	ValueFormatter(),
22 	fConfig(config)
23 {
24 	if (fConfig != NULL)
25 		fConfig->AcquireReference();
26 }
27 
28 
29 IntegerValueFormatter::~IntegerValueFormatter()
30 {
31 	if (fConfig != NULL)
32 		fConfig->ReleaseReference();
33 }
34 
35 
36 Settings*
37 IntegerValueFormatter::GetSettings() const
38 {
39 	return fConfig != NULL ? fConfig->GetSettings() : NULL;
40 }
41 
42 
43 status_t
44 IntegerValueFormatter::FormatValue(Value* _value, BString& _output)
45 {
46 	IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
47 	if (value == NULL)
48 		return B_BAD_VALUE;
49 
50 	// format the value
51 	integer_format format = fConfig != NULL
52 		? fConfig->IntegerFormat() : INTEGER_FORMAT_DEFAULT;
53 	char buffer[32];
54 	if (!IntegerFormatter::FormatValue(value->GetValue(), format,  buffer,
55 			sizeof(buffer))) {
56 		return B_BAD_VALUE;
57 	}
58 
59 	_output.SetTo(buffer);
60 
61 	return B_OK;
62 }
63 
64 
65 bool
66 IntegerValueFormatter::SupportsValidation() const
67 {
68 	return true;
69 }
70 
71 
72 bool
73 IntegerValueFormatter::ValidateFormattedValue(const BString& input,
74 	type_code type) const
75 {
76 	::Value* value = NULL;
77 	return _PerformValidation(input, type, value, false) == B_OK;
78 }
79 
80 
81 status_t
82 IntegerValueFormatter::GetValueFromFormattedInput(const BString& input,
83 	type_code type, Value*& _output) const
84 {
85 	return _PerformValidation(input, type, _output, true);
86 }
87 
88 
89 status_t
90 IntegerValueFormatter::_PerformValidation(const BString& input, type_code type,
91 	::Value*& _output, bool wantsValue) const
92 {
93 	integer_format format;
94 	if (fConfig != NULL)
95 		format = fConfig->IntegerFormat();
96 	else {
97 		bool isSigned;
98 		if (BVariant::TypeIsInteger(type, &isSigned)) {
99 			format = isSigned ? INTEGER_FORMAT_SIGNED
100 				: INTEGER_FORMAT_UNSIGNED;
101 		} else
102 			return B_BAD_VALUE;
103 	}
104 
105 	status_t error = B_OK;
106 	if (format == INTEGER_FORMAT_UNSIGNED
107 		|| format >= INTEGER_FORMAT_HEX_DEFAULT) {
108 		error = _ValidateUnsigned(input, type, _output, format, wantsValue);
109 	} else
110 		error = _ValidateSigned(input, type, _output, wantsValue);
111 
112 	return error;
113 }
114 
115 
116 status_t
117 IntegerValueFormatter::_ValidateSigned(const BString& input, type_code type,
118 	::Value*& _output, bool wantsValue) const
119 {
120 	const char* text = input.String();
121 	char *parseEnd = NULL;
122 	intmax_t parsedValue = strtoimax(text, &parseEnd, 10);
123 	if (parseEnd - text < input.Length() && !isspace(*parseEnd))
124 		return B_NO_MEMORY;
125 
126 	BVariant newValue;
127 	switch (type) {
128 		case B_INT8_TYPE:
129 		{
130 			if (parsedValue < INT8_MIN || parsedValue > INT8_MAX)
131 				return B_BAD_VALUE;
132 
133 			newValue.SetTo((int8)parsedValue);
134 			break;
135 		}
136 		case B_INT16_TYPE:
137 		{
138 			if (parsedValue < INT16_MIN || parsedValue > INT16_MAX)
139 				return B_BAD_VALUE;
140 
141 			newValue.SetTo((int16)parsedValue);
142 			break;
143 		}
144 		case B_INT32_TYPE:
145 		{
146 			if (parsedValue < INT32_MIN || parsedValue > INT32_MAX)
147 				return B_BAD_VALUE;
148 
149 			newValue.SetTo((int32)parsedValue);
150 			break;
151 		}
152 		case B_INT64_TYPE:
153 		{
154 			newValue.SetTo((int64)parsedValue);
155 			break;
156 		}
157 		default:
158 			return B_BAD_VALUE;
159 	}
160 
161 	if (wantsValue) {
162 		_output = new(std::nothrow) IntegerValue(newValue);
163 		if (_output == NULL)
164 			return B_NO_MEMORY;
165 	}
166 
167 	return B_OK;
168 }
169 
170 
171 status_t
172 IntegerValueFormatter::_ValidateUnsigned(const BString& input, type_code type,
173 	::Value*& _output, integer_format format, bool wantsValue) const
174 {
175 	const char* text = input.String();
176 	int32 base = format == INTEGER_FORMAT_UNSIGNED ? 10 : 16;
177 
178 	char *parseEnd = NULL;
179 	uintmax_t parsedValue = strtoumax(text, &parseEnd, base);
180 	if (parseEnd - text < input.Length() && !isspace(*parseEnd))
181 		return B_BAD_VALUE;
182 
183 	BVariant newValue;
184 	switch (type) {
185 		case B_UINT8_TYPE:
186 		{
187 			if (parsedValue > UINT8_MAX)
188 				return B_BAD_VALUE;
189 
190 			newValue.SetTo((uint8)parsedValue);
191 			break;
192 		}
193 		case B_UINT16_TYPE:
194 		{
195 			if (parsedValue > UINT16_MAX)
196 				return B_BAD_VALUE;
197 
198 			newValue.SetTo((uint16)parsedValue);
199 			break;
200 		}
201 		case B_UINT32_TYPE:
202 		{
203 			if (parsedValue > UINT32_MAX)
204 				return B_BAD_VALUE;
205 
206 			newValue.SetTo((uint32)parsedValue);
207 			break;
208 		}
209 		case B_UINT64_TYPE:
210 		{
211 			newValue.SetTo((uint64)parsedValue);
212 			break;
213 		}
214 		default:
215 			return B_BAD_VALUE;
216 	}
217 
218 	if (wantsValue) {
219 		_output = new(std::nothrow) IntegerValue(newValue);
220 		if (_output == NULL)
221 			return B_NO_MEMORY;
222 	}
223 
224 	return B_OK;
225 }
226 
227 
228 
229 // #pragma mark - Config
230 
231 
232 IntegerValueFormatter::Config::~Config()
233 {
234 }
235