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