* Copyright 2015, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "IntegerValueFormatter.h"
#include <new>
#include <ctype.h>
#include "IntegerFormatter.h"
#include "IntegerValue.h"
IntegerValueFormatter::IntegerValueFormatter(Config* config)
:
ValueFormatter(),
fConfig(config)
{
if (fConfig != NULL)
fConfig->AcquireReference();
}
IntegerValueFormatter::~IntegerValueFormatter()
{
if (fConfig != NULL)
fConfig->ReleaseReference();
}
Settings*
IntegerValueFormatter::GetSettings() const
{
return fConfig != NULL ? fConfig->GetSettings() : NULL;
}
status_t
IntegerValueFormatter::FormatValue(Value* _value, BString& _output)
{
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
if (value == NULL)
return B_BAD_VALUE;
integer_format format = fConfig != NULL
? fConfig->IntegerFormat() : INTEGER_FORMAT_DEFAULT;
char buffer[32];
if (!IntegerFormatter::FormatValue(value->GetValue(), format, buffer,
sizeof(buffer))) {
return B_BAD_VALUE;
}
_output.SetTo(buffer);
return B_OK;
}
bool
IntegerValueFormatter::SupportsValidation() const
{
return true;
}
bool
IntegerValueFormatter::ValidateFormattedValue(const BString& input,
type_code type) const
{
::Value* value = NULL;
return _PerformValidation(input, type, value, false) == B_OK;
}
status_t
IntegerValueFormatter::GetValueFromFormattedInput(const BString& input,
type_code type, Value*& _output) const
{
return _PerformValidation(input, type, _output, true);
}
status_t
IntegerValueFormatter::_PerformValidation(const BString& input, type_code type,
::Value*& _output, bool wantsValue) const
{
integer_format format;
if (fConfig != NULL)
format = fConfig->IntegerFormat();
else {
bool isSigned;
if (BVariant::TypeIsInteger(type, &isSigned)) {
format = isSigned ? INTEGER_FORMAT_SIGNED
: INTEGER_FORMAT_UNSIGNED;
} else
return B_BAD_VALUE;
}
status_t error = B_OK;
if (format == INTEGER_FORMAT_UNSIGNED
|| format >= INTEGER_FORMAT_HEX_DEFAULT) {
error = _ValidateUnsigned(input, type, _output, format, wantsValue);
} else
error = _ValidateSigned(input, type, _output, wantsValue);
return error;
}
status_t
IntegerValueFormatter::_ValidateSigned(const BString& input, type_code type,
::Value*& _output, bool wantsValue) const
{
const char* text = input.String();
char *parseEnd = NULL;
intmax_t parsedValue = strtoimax(text, &parseEnd, 10);
if (parseEnd - text < input.Length() && !isspace(*parseEnd))
return B_NO_MEMORY;
BVariant newValue;
switch (type) {
case B_INT8_TYPE:
{
if (parsedValue < INT8_MIN || parsedValue > INT8_MAX)
return B_BAD_VALUE;
newValue.SetTo((int8)parsedValue);
break;
}
case B_INT16_TYPE:
{
if (parsedValue < INT16_MIN || parsedValue > INT16_MAX)
return B_BAD_VALUE;
newValue.SetTo((int16)parsedValue);
break;
}
case B_INT32_TYPE:
{
if (parsedValue < INT32_MIN || parsedValue > INT32_MAX)
return B_BAD_VALUE;
newValue.SetTo((int32)parsedValue);
break;
}
case B_INT64_TYPE:
{
newValue.SetTo((int64)parsedValue);
break;
}
default:
return B_BAD_VALUE;
}
if (wantsValue) {
_output = new(std::nothrow) IntegerValue(newValue);
if (_output == NULL)
return B_NO_MEMORY;
}
return B_OK;
}
status_t
IntegerValueFormatter::_ValidateUnsigned(const BString& input, type_code type,
::Value*& _output, integer_format format, bool wantsValue) const
{
const char* text = input.String();
int32 base = format == INTEGER_FORMAT_UNSIGNED ? 10 : 16;
char *parseEnd = NULL;
uintmax_t parsedValue = strtoumax(text, &parseEnd, base);
if (parseEnd - text < input.Length() && !isspace(*parseEnd))
return B_BAD_VALUE;
BVariant newValue;
switch (type) {
case B_UINT8_TYPE:
{
if (parsedValue > UINT8_MAX)
return B_BAD_VALUE;
newValue.SetTo((uint8)parsedValue);
break;
}
case B_UINT16_TYPE:
{
if (parsedValue > UINT16_MAX)
return B_BAD_VALUE;
newValue.SetTo((uint16)parsedValue);
break;
}
case B_UINT32_TYPE:
{
if (parsedValue > UINT32_MAX)
return B_BAD_VALUE;
newValue.SetTo((uint32)parsedValue);
break;
}
case B_UINT64_TYPE:
{
newValue.SetTo((uint64)parsedValue);
break;
}
default:
return B_BAD_VALUE;
}
if (wantsValue) {
_output = new(std::nothrow) IntegerValue(newValue);
if (_output == NULL)
return B_NO_MEMORY;
}
return B_OK;
}
IntegerValueFormatter::Config::~Config()
{
}