diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-10-23 13:21:10 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-10-23 13:21:10 -0500 |
commit | 5cc7cbc3704ec255eb5d0ac53b2cc0fcb1221d63 (patch) | |
tree | 169d4d2d8dffe014851712e31a55036deb0c7c0c /source/fud_string_convert.cpp | |
parent | b2dbcb55e2832c373fecb4033a3ed77e5dbc77aa (diff) |
String conversion and parsing format spec.
Diffstat (limited to 'source/fud_string_convert.cpp')
-rw-r--r-- | source/fud_string_convert.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/source/fud_string_convert.cpp b/source/fud_string_convert.cpp new file mode 100644 index 0000000..428ab36 --- /dev/null +++ b/source/fud_string_convert.cpp @@ -0,0 +1,110 @@ +/* + * libfud + * Copyright 2024 Dominick Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fud_string_convert.hpp" + +namespace fud::impl { + +FudStatus checkPlusSigned(StringView& view, size_t& skipIndex) +{ + auto isPlusSigned = view.data()[0] == '+'; + if (isPlusSigned && view.length() == 1) { + return FudStatus::ArgumentInvalid; + } + if (isPlusSigned) { + view.advanceUnsafe(); + skipIndex++; + } + return FudStatus::Success; +} + +Result<bool, FudStatus> checkNegative(StringView& view, size_t& skipIndex) +{ + bool isNegative = view.data()[0] == '-'; + if (isNegative && view.length() == 1) { + return FudStatus::ArgumentInvalid; + } + if (isNegative) { + skipIndex += 1; + view.advanceUnsafe(); + } + return isNegative; +} + +Result<Radix, FudStatus> determineRadix(StringView input, size_t& index) +{ + if (input.length() < 1) { + return FudStatus::ArgumentInvalid; + } + + if (input.length() == 1 && input.data()[0] == '0') { + return Radix::Octal; + } + + if (input.length() == 1) { + return Radix::Decimal; + } + + if (input.data()[0] == '0' && (input.data()[1] == 'x' || input.data()[1] == 'X')) { + index += 2; + return Radix::Hexadecimal; + } + + if (input.data()[0] == '0') { + auto nextChar = input.data()[1]; + auto nextVal = AsciiLookup[nextChar]; + if (nextVal >= 0 && nextVal < static_cast<uint8_t>(Radix::Octal)) { + return Radix::Octal; + } + if (nextVal >= static_cast<uint8_t>(Radix::Octal)) { + return FudStatus::ArgumentInvalid; + } + } + + return Radix::Decimal; +} + +Result<uint8_t, FudStatus> getRadix(StringView& view, size_t& skipIndex, Option<uint8_t> specifiedRadixOption) +{ + if (specifiedRadixOption.isNone()) { + size_t radixIndex = 0; + auto status = determineRadix(view, radixIndex); + if (status.isOkay()) { + skipIndex += radixIndex; + view.advanceUnsafe(radixIndex); + return static_cast<uint8_t>(status.takeOkay()); + } + return status.takeError(); + } + + auto radix = specifiedRadixOption.value(); + if (radix == static_cast<uint8_t>(Radix::Hexadecimal) && view.length() > 2 && + (view.data()[1] == 'x' || view.data()[1] == 'X')) { + skipIndex += 2; + view.advanceUnsafe(2); + } else if (radix == static_cast<uint8_t>(Radix::Binary) && view.length() > 2 && view.data()[1] == 'b') { + skipIndex += 2; + view.advanceUnsafe(2); + } else if (radix == static_cast<uint8_t>(Radix::Octal) && view.length() > 2 && view.data()[1] == '0') { + skipIndex += 2; + view.advanceUnsafe(2); + } + + return radix; +} + +} // namespace fud::impl |