From 67f536cf91633753f26efba6e3ece173c38c6fb5 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 5 Nov 2022 10:50:58 +0100 Subject: [PATCH] Kernel: Split number-parsing code into a separate file --- kernel/include/utils/StringParsing.h | 4 +++ kernel/src/init/InitRD.cpp | 21 ++++-------- kernel/src/utils/StringParsing.cpp | 49 ++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 kernel/include/utils/StringParsing.h create mode 100644 kernel/src/utils/StringParsing.cpp diff --git a/kernel/include/utils/StringParsing.h b/kernel/include/utils/StringParsing.h new file mode 100644 index 00000000..264644f6 --- /dev/null +++ b/kernel/include/utils/StringParsing.h @@ -0,0 +1,4 @@ +#pragma once + +long parse_decimal(const char* str); +long parse_octal(const char* str); \ No newline at end of file diff --git a/kernel/src/init/InitRD.cpp b/kernel/src/init/InitRD.cpp index ea2bd4ee..eee9cd80 100644 --- a/kernel/src/init/InitRD.cpp +++ b/kernel/src/init/InitRD.cpp @@ -10,6 +10,7 @@ #include "std/errno.h" #include "std/stdlib.h" #include "std/string.h" +#include "utils/StringParsing.h" extern BOOTBOOT bootboot; @@ -54,24 +55,14 @@ uint64_t InitRD::get_file_physical_address(InitRD::File& file) InitRD::File InitRD::get_file(TarHeader* header) { File result; - result.size = 0; + char null_terminated_size[13]; + memcpy(null_terminated_size, header->size, 12); + null_terminated_size[12] = 0; + result.size = parse_octal(null_terminated_size); memcpy(result.name, header->name, 100); - long multiplier = - 1; // why they decided to store the size as an octal-encoded string instead of an integer is beyond me - for (int i = 10; i >= 0; i--) - { - result.size += (multiplier * (header->size[i] - 48)); - multiplier *= 8; - } result.addr = (void*)((uint64_t)header + TAR_BLOCKSIZE); result.size_in_blocks = Utilities::get_blocks_from_size(TAR_BLOCKSIZE, result.size); - result.mode = 0; - multiplier = 1; - for (int i = 6; i >= 0; i--) - { - result.mode += (mode_t)(multiplier * (header->mode[i] - 48)); - multiplier *= 8; - } + result.mode = (mode_t)parse_octal(header->mode); return result; } diff --git a/kernel/src/utils/StringParsing.cpp b/kernel/src/utils/StringParsing.cpp new file mode 100644 index 00000000..0662aa52 --- /dev/null +++ b/kernel/src/utils/StringParsing.cpp @@ -0,0 +1,49 @@ +#include "utils/StringParsing.h" + +int isdigit(int c) +{ + return c >= '0' && c < ':'; +} + +int isodigit(int c) +{ + return c >= '0' && c < '8'; +} + +int isxdigit(int c) +{ + return isdigit(c) || ((unsigned int)c | 32) - 'a' < 6; +} + +template +static T string_to_integer_type(const char* str, int base, ValidDigitChecker checker, Converter converter) +{ + bool neg = false; + T val = 0; + + switch (*str) + { + case '-': + neg = true; + str++; + break; + case '+': str++; break; + default: break; + } + + while (checker(*str)) { val = (base * val) + converter(*str++); } + + return (neg ? -val : val); +} + +long parse_decimal(const char* str) +{ + return string_to_integer_type( + str, 10, [](char c) { return isdigit(c); }, [](char c) { return c - '0'; }); +} + +long parse_octal(const char* str) +{ + return string_to_integer_type( + str, 8, [](char c) { return isodigit(c); }, [](char c) { return c - '0'; }); +} \ No newline at end of file