From 919ad9d1022edec7fdd97f74ef50de26dde6aebb Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Fri, 5 Feb 2021 23:15:37 +0200 Subject: Add IntegerView --- .clang-format | 6 +++ kernel.cc | 104 ++++++++++++++++++++-------------------------- libk/makefile | 7 +++- libk/stdlib.h | 31 ++++++++------ libk/stdlib/console.cc | 8 ++-- libk/string.cc | 22 +++++----- libk/string.h | 106 ++++++++++++++++++++++++++++++++++++----------- libk/type_traits.h | 12 ++++-- libk/type_traits/test.cc | 17 ++++++++ libk/types.h | 1 - makefile | 10 +++-- vga.cc | 41 ++++++------------ vga.h | 10 ++--- 13 files changed, 221 insertions(+), 154 deletions(-) create mode 100644 .clang-format create mode 100644 libk/type_traits/test.cc diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..ee8a219 --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +--- +BasedOnStyle: Chromium +ColumnLimit: '120' +AccessModifierOffset: '-2' + +... diff --git a/kernel.cc b/kernel.cc index b2e2b01..3045374 100644 --- a/kernel.cc +++ b/kernel.cc @@ -8,10 +8,10 @@ #error "This tutorial needs to be compiled with a ix86-elf compiler" #endif -#include "multiboot2.h" -#include "vga.h" #include #include +#include "multiboot2.h" +#include "vga.h" extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) { VGA terminal; @@ -19,69 +19,57 @@ extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) { printk("Hello, kernel World!\n"); - printk("multiboot magic: 0x", mb_magic, - mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " is valid" : " is invalid", - '\n'); - printk("multiboot addr: 0x", mb_addr, '\n'); + printk("multiboot magic: ", uhex{mb_magic}, mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " valid" : " invalid", '\n'); + printk("multiboot addr: ", uhex{mb_addr}, !(mb_addr & 7) ? " is aligned" : " is not aligned", '\n'); - if (mb_addr & 7) { - printk("unaligned mbi\n"); - } + struct multiboot_tag* tag; + const uint32_t size = *(unsigned*)mb_addr; + printk("Announced mbi size ", size, '\n'); - struct multiboot_tag *tag; - const uint32_t size = *(unsigned *)mb_addr; - printk("Announced mbi size 0x", size, '\n'); + for (tag = (struct multiboot_tag*)(mb_addr + 8); tag->type != MULTIBOOT_TAG_TYPE_END; + tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7))) { + switch (tag->type) { + case MULTIBOOT_TAG_TYPE_CMDLINE: { + auto* t = reinterpret_cast(tag); + printk("Command line = [", t->string, "]\n"); + } break; - for (tag = (struct multiboot_tag *)(mb_addr + 8); - tag->type != MULTIBOOT_TAG_TYPE_END; - tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag + - ((tag->size + 7) & ~7))) { + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: { + auto* t = reinterpret_cast(tag); + printk("Boot loader name = [", t->string, "]\n"); + } break; - switch (tag->type) { - case MULTIBOOT_TAG_TYPE_CMDLINE: - printk("Command line = [", ((struct multiboot_tag_string *)tag)->string, - "]\n"); - break; - case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: - printk("Boot loader name = [", - ((struct multiboot_tag_string *)tag)->string, "]\n"); - break; - case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: - printk("mem_lower = ", - ((struct multiboot_tag_basic_meminfo *)tag)->mem_lower, "KB\n", - "mem_upper = ", - ((struct multiboot_tag_basic_meminfo *)tag)->mem_upper, "KB\n"); - break; - case MULTIBOOT_TAG_TYPE_BOOTDEV: - printk("Boot device 0x", ((struct multiboot_tag_bootdev *)tag)->biosdev, - " slice ", ((struct multiboot_tag_bootdev *)tag)->slice, " part ", - ((struct multiboot_tag_bootdev *)tag)->part, '\n'); - break; - case MULTIBOOT_TAG_TYPE_MMAP: { - multiboot_memory_map_t *mmap; + case MULTIBOOT_TAG_TYPE_BOOTDEV: { + auto* t = reinterpret_cast(tag); + printk("Boot device ", uhex{t->biosdev}, " slice ", t->slice, " part ", t->part, '\n'); + } break; + + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: { + auto* t = reinterpret_cast(tag); + printk("mem_lower = ", t->mem_lower, "KB\n", "mem_upper = ", t->mem_upper, "KB\n"); + } break; + + case MULTIBOOT_TAG_TYPE_MMAP: { + auto* t = reinterpret_cast(tag); + multiboot_memory_map_t* mmap; - printk("mmap\n"); + printk("memory map\n"); + for (mmap = t->entries; (multiboot_uint8_t*)mmap < (multiboot_uint8_t*)tag + tag->size; + mmap = (multiboot_memory_map_t*)((unsigned long)mmap + ((struct multiboot_tag_mmap*)tag)->entry_size)) { + printk(" base_addr = ", uhex{(unsigned)(mmap->addr >> 32)}, ' ', uhex{(unsigned)(mmap->addr & 0xffffffff)}); + printk(" length = ", (unsigned)(mmap->len >> 32), ' ', (unsigned)(mmap->len & 0xffffffff)); + printk(" type = ", (unsigned)mmap->type, '\n'); + } + } break; - for (mmap = ((struct multiboot_tag_mmap *)tag)->entries; - (multiboot_uint8_t *)mmap < (multiboot_uint8_t *)tag + tag->size; - mmap = (multiboot_memory_map_t *)((unsigned long)mmap + - ((struct multiboot_tag_mmap *)tag) - ->entry_size)) - printk(" base_addr = 0x", (unsigned)(mmap->addr >> 32), ' ', - (unsigned)(mmap->addr & 0xffffffff), " length = 0x", - (unsigned)(mmap->len >> 32), ' ', - (unsigned)(mmap->len & 0xffffffff), " type = 0x", - (unsigned)mmap->type, '\n'); - } break; - default: - printk("Tag 0x", tag->type, ", Size 0x", tag->size, '\n'); - break; - } // switch(tag->type) - } // for(each tag) + default: + printk("Tag ", tag->type, ", Size ", tag->size, '\n'); + break; + } // switch(tag->type) + } // for(each tag) - tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag + - ((tag->size + 7) & ~7)); - printk("Total mbi size 0x", (unsigned)tag - mb_addr, '\n'); + tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7)); + printk("Total mbi size ", (unsigned)tag - mb_addr, '\n'); abort(); } diff --git a/libk/makefile b/libk/makefile index faf5b79..941d93d 100644 --- a/libk/makefile +++ b/libk/makefile @@ -1,11 +1,14 @@ CXX_OBJ := string.o stdlib/console.o +CXX_TEST_OBJ := type_traits/test.o libk.a: $(CXX_OBJ) $(AR) rcs $@ $(CXX_OBJ) -$(CXX_OBJ): %.o : %.cc +test: $(CXX_TEST_OBJ) + +$(CXX_OBJ) $(CXX_TEST_OBJ): %.o : %.cc $(CXX) -target $(TARGET) $(CXX_FLAGS) -I$(CURDIR) -c $^ -o $@ clean: - rm libk.a $(CXX_OBJ) + rm -f libk.a $(CXX_OBJ) $(CXX_TEST_OBJ) diff --git a/libk/stdlib.h b/libk/stdlib.h index 44bacf4..f031408 100644 --- a/libk/stdlib.h +++ b/libk/stdlib.h @@ -4,27 +4,34 @@ #include class Console { -public: + public: virtual void write(char c) = 0; - virtual void write(const String &msg) = 0; - virtual void write(int n) = 0; - virtual void write(unsigned int n) = 0; + virtual void write(ViewIterator& msg) = 0; - static void set(Console *ptr); - static Console *get(); + static void set(Console* ptr); + static Console* get(); }; -template void printk(const T &a) { - if (auto *c = Console::get()) { - if constexpr (is_same()) - c->write(String(a)); - else +template +void printk(const T& a) { + if (auto* c = Console::get()) { + if constexpr (is_same()) { + c->write(a); + } else if constexpr (requires { StringView(a); }) { + StringView v(a); + auto iter = v.begin(); + c->write(iter); + } else if constexpr (requires { IntegerView(a); }) { + IntegerView v(a); + auto iter = v.begin(); + c->write(iter); + } else c->write(a); } } template -void printk(const T &a, const Args &...x) { +void printk(const T& a, const Args&... x) { printk(a); printk(x...); } diff --git a/libk/stdlib/console.cc b/libk/stdlib/console.cc index dee6a8f..308f055 100644 --- a/libk/stdlib/console.cc +++ b/libk/stdlib/console.cc @@ -1,14 +1,16 @@ #include "stdlib.h" -static Console *global_console = nullptr; +static Console* global_console = nullptr; -void Console::set(Console *ptr) { +void Console::set(Console* ptr) { if (ptr != nullptr) { global_console = ptr; } } -Console *Console::get() { return global_console; } +Console* Console::get() { + return global_console; +} void abort() { /* diff --git a/libk/string.cc b/libk/string.cc index 5cd4bb2..c75feb1 100644 --- a/libk/string.cc +++ b/libk/string.cc @@ -8,19 +8,19 @@ // int strncmp(const char *s1, const char *s2, int c); /* strcmp - compare two C-strings */ -constexpr int strcmp(const char *s1, const char *s2) -{ - const auto s1_len = strlen(s1); - for(size_t i = 0; i < s1_len; ++i) { - if(s1[i] == s2[i]) continue; - if(s1[i] > s2[i]) return 1; - if(s1[i] < s2[i]) return -1; - } - return 0; +constexpr int strcmp(const char* s1, const char* s2) { + const auto s1_len = strlen(s1); + for (size_t i = 0; i < s1_len; ++i) { + if (s1[i] == s2[i]) + continue; + if (s1[i] > s2[i]) + return 1; + if (s1[i] < s2[i]) + return -1; + } + return 0; } static_assert(strcmp("one", "one") == 0); static_assert(strcmp("one", "two") < 0); static_assert(strcmp("foo", "bar") > 0); - - diff --git a/libk/string.h b/libk/string.h index deb6fde..0675cea 100644 --- a/libk/string.h +++ b/libk/string.h @@ -1,19 +1,24 @@ #pragma once -#include "types.h" - -constexpr size_t strlen(const char *str) { - int len = 0; +#include +#include + +/** + * Calculate the length of the string (in bytes) pointed to by str, excluding + * the terminating null character. + */ +constexpr size_t strlen(const char* str) { + size_t len = 0; while (str[len]) ++len; return len; } /* reverse: reverse string s in place */ -constexpr void reverse(char s[]) { +constexpr void reverse(char s[], int strlen) { int i, j; char c; - for (i = 0, j = strlen(s) - 1; i < j; i++, j--) { + for (i = 0, j = strlen - 1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; @@ -21,49 +26,100 @@ constexpr void reverse(char s[]) { } /* itoa: convert n to characters in s */ -template constexpr void itoa(int n, char s[]) { - int i, sign; - - if ((sign = n) < 0) /* record sign */ - n = -n; /* make n positive */ +template +constexpr size_t itoa(T n, char s[]) { + const bool is_negative = (n < 0); + if constexpr (!is_unsigned()) { + if (n < 0) + n = -n; + } - i = 0; - do { /* generate digits in reverse order */ + int i = 0; + do { /* generate digits in reverse order */ s[i++] = "0123456789abcdef"[n % base]; /* get next digit */ } while ((n /= base) > 0); /* delete it */ - if (sign < 0) + if (is_negative) s[i++] = '-'; s[i] = '\0'; - reverse(s); + reverse(s, i); + return i; } -class String { +class ViewIterator { public: - class Iterator { - friend class String; + virtual char next() = 0; + virtual operator bool() const = 0; +}; + +class StringView { +public: + class Iterator : public ViewIterator { + friend class StringView; public: - char next() { return p->buffer[pos++]; } - operator bool() const { return (pos < p->m_length); } + char next() override { return p->buffer[pos++]; } + operator bool() const override { return (pos < p->m_length); } private: - Iterator(const String *s) : p(s) {} + Iterator(const StringView* s) : p(s) {} size_t pos = 0; - const String *p; + const StringView* p; }; friend class Iterator; - String(const char *d) : buffer{d}, m_length{strlen(d)} {} - String(const char *d, size_t l) : buffer{d}, m_length{l} {} + StringView(const char* d) : buffer{d}, m_length{strlen(d)} {} + StringView(const char* d, size_t l) : buffer{d}, m_length{l} {} Iterator begin() const { return Iterator(this); } private: - const char *const buffer; + const char* const buffer; const size_t m_length; }; + +class IntegerView { +public: + template + struct HexFormat { + T n; + }; + + class Iterator : public ViewIterator { + friend class IntegerView; + + public: + char next() override { return _p->buffer[pos++]; }; + operator bool() const override { return (pos < _p->length); } + + private: + Iterator(const IntegerView* v) : _p(v) {} + + size_t pos = 0; + const IntegerView* _p; + }; + + IntegerView(int32_t n) { length = itoa(n, buffer); } + + template + IntegerView(HexFormat f) { + buffer[0] = '0'; + buffer[1] = 'x'; + length = itoa(f.n, buffer + 2) + 2; + } + + Iterator begin() const { return Iterator(this); } + +private: + char buffer[128]; + size_t length = 0; +}; + +using hex = IntegerView::HexFormat; +using uhex = IntegerView::HexFormat; + +using hex_addr = IntegerView::HexFormat; // TODO causes crash diff --git a/libk/type_traits.h b/libk/type_traits.h index cef30c1..dc70339 100644 --- a/libk/type_traits.h +++ b/libk/type_traits.h @@ -1,10 +1,16 @@ #pragma once -template struct integral_constant { +template +struct integral_constant { constexpr T operator()() const { return v; } constexpr operator T() const { return v; } }; -template struct is_same : integral_constant {}; +template +struct is_same : integral_constant {}; -template struct is_same : integral_constant {}; +template +struct is_same : integral_constant {}; + +template +struct is_unsigned : integral_constant(-1))> {}; diff --git a/libk/type_traits/test.cc b/libk/type_traits/test.cc new file mode 100644 index 0000000..1aa11df --- /dev/null +++ b/libk/type_traits/test.cc @@ -0,0 +1,17 @@ +#include +#include + +// is_same +static_assert(is_same() == true); +static_assert(is_same() == false); + +// is_unsigned +static_assert(is_unsigned() == true); +static_assert(is_unsigned() == true); +static_assert(is_unsigned() == true); +static_assert(is_unsigned() == true); + +static_assert(is_unsigned() == false); +static_assert(is_unsigned() == false); +static_assert(is_unsigned() == false); +static_assert(is_unsigned() == false); diff --git a/libk/types.h b/libk/types.h index be38cb0..fc20d22 100644 --- a/libk/types.h +++ b/libk/types.h @@ -3,7 +3,6 @@ typedef unsigned short size_t; static_assert(sizeof(size_t) >= 2); - typedef unsigned char uint8_t; static_assert(sizeof(uint8_t) == 1); diff --git a/makefile b/makefile index 9c2728c..f45d65a 100644 --- a/makefile +++ b/makefile @@ -35,19 +35,21 @@ $(CXX_OBJ): %.o : %.cc libk/libk.a: $(MAKE) -C libk libk.a +libk/test: + $(MAKE) -C libk test +test: libk/test + iso: glitch.elf mkdir -p isodir/boot/grub cp glitch.elf isodir/boot/glitch.elf cp grub.cfg isodir/boot/grub/grub.cfg grub-mkrescue -o myos.iso isodir -run: glitch.elf - qemu-system-i386 -kernel glitch.elf -run-iso: iso +run: iso qemu-system-i386 -cdrom myos.iso clean: - rm boot.o $(CXX_OBJ) glitch.elf + rm -f boot.o $(CXX_OBJ) glitch.elf $(MAKE) -C libk clean clean-iso: diff --git a/vga.cc b/vga.cc index a696d77..83d0060 100644 --- a/vga.cc +++ b/vga.cc @@ -11,7 +11,7 @@ constexpr uint16_t vga_entry(unsigned char uc, uint8_t color) { VGA::VGA(vga_color fg, vga_color bg, uint32_t address) { color = vga_entry_color(fg, bg); - buffer = (uint16_t *)address; + buffer = (uint16_t*)address; // clear buffer for (size_t y = 0; y < max_rows; y++) { @@ -22,20 +22,17 @@ VGA::VGA(vga_color fg, vga_color bg, uint32_t address) { } } -void VGA::put_char(char c, size_t x, size_t y, uint8_t color) { - const size_t index = y * max_columns + x; - buffer[index] = vga_entry(c, (color == 0) ? this->color : color); -} - void VGA::write(char c) { switch (c) { - case '\n': - column = 0; - ++row; - break; - default: - put_char(c, column, row, color); - ++column; + case '\n': + column = 0; + ++row; + break; + default: { + const size_t index = row * max_columns + column; + buffer[index] = vga_entry(c, (color == 0) ? this->color : color); + ++column; + } } if (column == max_columns) { @@ -57,20 +54,8 @@ void VGA::write(char c) { } } -void VGA::write(const String &data) { - auto it = data.begin(); - while (it) { - write(it.next()); +void VGA::write(ViewIterator& iter) { + while (iter) { + write(iter.next()); } } - -void VGA::write(int n) { - char buffer[max_columns]; - itoa<16>(n, buffer); - write(buffer); -} - -void VGA::write(unsigned int n) { - // TODO - write((int)n); -} diff --git a/vga.h b/vga.h index f6fbbef..3052dbc 100644 --- a/vga.h +++ b/vga.h @@ -23,15 +23,11 @@ public: VGA_COLOR_WHITE = 15, }; - VGA(vga_color fg = VGA_COLOR_BLACK, vga_color bg = VGA_COLOR_LIGHT_GREY, - uint32_t address = 0xB8000); + VGA(vga_color fg = VGA_COLOR_BLACK, vga_color bg = VGA_COLOR_LIGHT_GREY, uint32_t address = 0xB8000); ~VGA() = default; - void put_char(char c, size_t x, size_t y, uint8_t color = 0); void write(char c) override; - void write(const String &data) override; - void write(int n) override; - void write(unsigned int n) override; + void write(ViewIterator& iter) override; void set_color(vga_color fg, vga_color bg) { color = (fg | bg << 4); } @@ -39,5 +35,5 @@ private: const size_t max_columns = 80, max_rows = 25; size_t column = 0, row = 0; uint8_t color; - uint16_t *buffer; + uint16_t* buffer; }; -- cgit v1.2.1