summaryrefslogtreecommitdiff
path: root/source/fud_string_convert.cpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-23 13:21:10 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-23 13:21:10 -0500
commit5cc7cbc3704ec255eb5d0ac53b2cc0fcb1221d63 (patch)
tree169d4d2d8dffe014851712e31a55036deb0c7c0c /source/fud_string_convert.cpp
parentb2dbcb55e2832c373fecb4033a3ed77e5dbc77aa (diff)
String conversion and parsing format spec.
Diffstat (limited to 'source/fud_string_convert.cpp')
-rw-r--r--source/fud_string_convert.cpp110
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