Compare commits

...

10 commits

Author SHA1 Message Date
Imbus
e1d1138653 Stuff from demos 2025-01-11 17:45:38 +01:00
Imbus
1515fcd2cf Format metatarget 2025-01-11 17:45:25 +01:00
Imbus
e13dce000a Default options in config.mk, test targets 2025-01-11 17:43:29 +01:00
Imbus
9f92308131 Add test target in meta makefile 2025-01-11 17:43:12 +01:00
Imbus
46201bbf59 Makefile fix 2025-01-11 17:43:04 +01:00
Imbus
5e89f20e02 Rm unused header 2025-01-11 17:33:31 +01:00
Imbus
7226b7aea6 Better tests 2025-01-11 17:33:21 +01:00
Imbus
91bf5ecec0 Some better assertion macros 2025-01-11 17:33:06 +01:00
Imbus
1a0b3697f2 Constuctor chaining, better/more efficient moving 2025-01-11 17:13:50 +01:00
Imbus
5c20408a04 Ignore 2025-01-10 08:16:19 +01:00
13 changed files with 270 additions and 23 deletions

1
.gitignore vendored
View file

@ -2,4 +2,5 @@
*.asm *.asm
*.o *.o
*.elf *.elf
build
compile_commands.json compile_commands.json

View file

@ -7,9 +7,18 @@ build: $(SUBDIRS)
$(MAKE) -j$(nproc) -C $$dir; \ $(MAKE) -j$(nproc) -C $$dir; \
done done
test: $(SUBDIRS) build
@for dir in $(SUBDIRS); do \
$(MAKE) -j$(nproc) test -C $$dir; \
done
clean: clean:
@for dir in $(SUBDIRS); do \ @for dir in $(SUBDIRS); do \
make -C $$dir clean; \ make -C $$dir clean; \
done done
.PHONY: build clean format:
find . -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.c" \) -exec clang-format -i {} \;
.PHONY: build clean test format

View file

@ -8,3 +8,24 @@
assert(cond); \ assert(cond); \
} \ } \
} while (0) } while (0)
#define ASSERT_EQ(expected, actual) \
do { \
if ((expected) != (actual)) { \
std::cerr << "Assertion failed: (" #expected " == " #actual ") " \
<< "Expected: " << (expected) \
<< ", Actual: " << (actual) << "\n"; \
assert((expected) == (actual)); \
} \
} while (0)
#define ASSERT_EQMSG(expected, actual, msg) \
do { \
if ((expected) != (actual)) { \
std::cerr << "Assertion failed: " << msg << "\n" \
<< "(" #expected " == " #actual ") " \
<< "Expected: " << (expected) \
<< ", Actual: " << (actual) << "\n"; \
assert((expected) == (actual)); \
} \
} while (0)

View file

@ -4,12 +4,22 @@ MAKEFLAGS += --no-print-directory
.PRECIOUS: %.o .PRECIOUS: %.o
.PRECIOUS: %.asm .PRECIOUS: %.asm
TARGET ?= main.elf
SRCS ?= $(wildcard *.cc)
HDRS ?= $(wildcard *.h)
OBJS = $(SRCS:.cc=.o) OBJS = $(SRCS:.cc=.o)
ASMS = $(SRCS:.cc=.asm) ASMS = $(SRCS:.cc=.asm)
all: $(TARGET) $(ASMS) all: $(TARGET) $(ASMS)
$(TARGET): $(OBJS) $(TARGET): $(OBJS)
test: $(TARGET)
./$(TARGET)
check: $(SRCS) $(HDRS)
cppcheck --language=c++ $^
asm: $(ASMS) asm: $(ASMS)
%.o: %.cc %.o: %.cc
@ -27,4 +37,4 @@ asm: $(ASMS)
clean: clean:
rm -f *.elf *.asm *.o rm -f *.elf *.asm *.o
.PHONY: clean all asm .PHONY: clean all asm check test

17
demos/comma.cpp Normal file
View file

@ -0,0 +1,17 @@
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main() {
std::string s;
while (cin >> s, s.length() > 5) {
cout << s << " is longer than 5\n";
}
cout << s << " is too short\n";
for (int i = 0, j = 0; i != 5; ++i, ++j) {
cout << i << ", " << j << endl;
}
}

24
demos/file_io_example.cpp Normal file
View file

@ -0,0 +1,24 @@
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
void print_bytes(std::string infile) {
std::ifstream in{infile};
int c;
while ((c = in.get()) != EOF) {
std::cout << "read: " << std::setw(3) << c << " [" << char(c) << "]"
<< std::endl;
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " filename" << std::endl;
return 1;
}
print_bytes(argv[1]);
return 0;
}

123
demos/map_and_set.cpp Normal file
View file

@ -0,0 +1,123 @@
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
#include <map>
#include <set>
void test_map() {
std::map<std::string, int> msi;
msi.insert(std::make_pair("Kalle", 1));
msi.emplace("Lisa", 2);
msi["Kim"] = 3;
for (const auto &a : msi) {
cout << a.first << " : " << a.second << endl;
}
cout << "Kim --> " << msi.at("Kim") << endl;
cout << "Lisa --> " << msi["Lisa"] << endl;
cout << "Hans --> " << msi["Hans"]
<< endl; // [] default-konstruerar ett värde
// för nycklar som inte finns
try {
cout << "Nisse --> " << msi.at("Nisse") << endl;
} catch (std::out_of_range &e) {
cout << "Nisse not found: " << e.what() << endl;
}
const auto &kim = msi.find("Kim");
if (kim != msi.end()) {
cout << "Kim : " << kim->second << endl;
} else {
cout << "Kim not found\n";
}
auto nisse = msi.find("Nisse");
if (nisse != msi.end()) {
cout << "Nisse : " << nisse->second << endl;
} else {
cout << "Nisse not found\n";
}
}
void test_set() {
std::set<int> ints{1, 3, 7};
ints.insert(5);
for (auto x : ints) {
cout << x << " ";
}
cout << endl;
auto has_one = ints.find(1);
if (has_one != ints.end()) {
cout << "one is in the set\n";
} else {
cout << "one is not in the set\n";
}
if (ints.count(1)) {
cout << "one is in the set\n";
} else {
cout << "one is not in the set\n";
}
auto has_two = ints.find(2);
if (has_two != ints.end()) {
cout << "two is in the set\n";
} else {
cout << "two is not in the set\n";
}
if (ints.count(2)) {
cout << "two is in the set\n";
} else {
cout << "two is not in the set\n";
}
auto has_five = ints.find(5);
if (has_five != ints.end()) {
cout << "five is in the set\n";
} else {
cout << "five is not in the set\n";
}
ints.erase(5);
auto has_five_now = ints.find(5);
if (has_five_now != ints.end()) {
cout << "five is in the set\n";
} else {
cout << "five is not in the set\n";
}
}
void test_set_bounds() {
std::set<int> ints{9, 1, 3, 7, 5};
auto lb3 = ints.lower_bound(3);
cout << "lb3: " << *lb3 << endl;
auto ub3 = ints.upper_bound(3);
cout << "ub3: " << *ub3 << endl;
auto lb4 = ints.lower_bound(4);
cout << "lb4: " << *lb4 << endl;
auto ub4 = ints.upper_bound(4);
cout << "ub4: " << *ub4 << endl;
auto er = ints.equal_range(7);
if (er.first == er.second) {
cout << "er.first == er.second";
}
cout << ", er.first: " << *er.first << ", er.second: " << *er.second
<< endl;
}
int main() {
test_map();
test_set();
test_set_bounds();
}

14
demos/print_seq.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef PRINT_SEQ_H
#define PRINT_SEQ_H
#include <iostream>
template <typename C> void print_seq(const C &c) {
using std::cout;
using std::endl;
cout << "[length: " << c.size() << "] ";
for (const auto &x : c) std::cout << x << " ";
cout << endl;
}
#endif

View file

@ -0,0 +1,15 @@
#include <iostream>
int main() {
int a{1234};
float f{1234.0};
std::cout << "sizeof(int): " << sizeof(int)
<< ", sizeof(float): " << sizeof(float) << std::endl;
std::cout << "static_cast: " << static_cast<float>(a) << " "
<< static_cast<int>(f) << std::endl;
std::cout << "reinterpret_cast: " << *reinterpret_cast<float *>(&a) << " "
<< *reinterpret_cast<int *>(&f) << std::endl;
}

View file

@ -1,6 +1,4 @@
TARGET = takewhile.elf TARGET = takewhile.elf
SRCS = takewhile.cc SRCS = takewhile.cc
all: $(TARGET)
include ../config.mk include ../config.mk

View file

@ -9,21 +9,26 @@ int main() {
Vec v; Vec v;
v.push_back(10); v.push_back(10);
ASSERT_MSG(v[0] == 10, "10 should be present at index 0"); int a = v[0];
ASSERT_EQMSG(10, a, "10 should be present at index 0");
Vec v2{1, 2, 3}; Vec v2{1, 2, 3};
ASSERT_MSG(v2.size() == 3, "Size should be three"); ASSERT_EQ(3, v2.size());
ASSERT_EQMSG(v2.size(), 3, "Size should be three");
v2.pop_back(); v2.pop_back();
ASSERT_EQ(2, v2.size());
ASSERT_MSG(v2.size() == 2, "Size should be three"); ASSERT_MSG(v2.size() == 2, "Size should be three");
// Triggers a reallocation (memcpy) // Triggers a reallocation (memcpy)
Vec v3{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; Vec v3{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
ASSERT_MSG(v3[11] == 12, "Index 11 should hold 12"); ASSERT_MSG(v3[11] == 12, "Index 11 should hold 12");
// ASSERT_MSG(v3[5] == 6, "Index 5 should hold 6"); // ??? ASSERT_MSG(v3[5] == 6, "Index 5 should hold 6"); // ???
ASSERT_MSG(v3.size() == 12, "Size should be 12"); ASSERT_EQ(12, v3.size());
ASSERT_MSG(v3.capacity() == 20, "Capacity should be 20"); ASSERT_EQ(24, v3.capacity());
for (const auto &a : v3) { Vec v_sized(40);
std::cout << a << std::endl; v_sized.push_back(0);
} ASSERT_MSG(v_sized[0] == 0, "Well");
return 0;
} }

View file

@ -3,13 +3,14 @@
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
Vec::Vec() : cap(INITIAL_LEN), w_idx(0), arr(nullptr) { Vec::Vec() : Vec(INITIAL_LEN) {}
std::cout << "Allocating vector" << std::endl;
arr = new T[INITIAL_LEN]; Vec::Vec(std::size_t size) : cap(size), w_idx(0), arr(new T[size]) {
std::cout << "Allocating vector of size " << size << std::endl;
} }
Vec::Vec(std::initializer_list<T> il) : Vec() { Vec::Vec(std::initializer_list<T> il) : Vec(il.size()) {
for (auto &a : il) push_back(a); for (auto &elem : il) push_back(std::move(elem));
} }
Vec::~Vec() { Vec::~Vec() {
@ -26,12 +27,18 @@ T &Vec::operator[](std::size_t idx) const noexcept {
exit(1); exit(1);
} }
void Vec::push_back(const T &value) noexcept { void Vec::push_back(const T &value) {
arr[w_idx++] = value; arr[w_idx++] = value;
if (w_idx == cap) { if (w_idx == cap)
resize(cap * 2);
}
void Vec::push_back(T &&value) {
arr[w_idx++] = std::move(value);
if (w_idx == cap)
resize(cap * 2); resize(cap * 2);
}
} }
std::size_t Vec::size() const { return w_idx; } std::size_t Vec::size() const { return w_idx; }
@ -39,9 +46,10 @@ std::size_t Vec::size() const { return w_idx; }
std::size_t Vec::capacity() const noexcept { return cap; } std::size_t Vec::capacity() const noexcept { return cap; }
void Vec::resize(std::size_t newsize) { void Vec::resize(std::size_t newsize) {
std::cout << "Reallocating" << std::endl; std::cout << "Reallocating: " << cap << " to " << newsize << std::endl;
T *newarr = new T[newsize]; T *newarr = new T[newsize];
std::memcpy(newarr, arr, w_idx); std::move(arr, arr + w_idx, newarr);
delete[] arr; delete[] arr;
arr = newarr; arr = newarr;
cap = newsize; cap = newsize;

View file

@ -13,6 +13,7 @@ class Vec {
public: public:
Vec(); Vec();
explicit Vec(std::size_t);
Vec(std::initializer_list<T>); Vec(std::initializer_list<T>);
Vec(const Vec &other); // Copy Vec(const Vec &other); // Copy
Vec(Vec &&other) noexcept; // Move Vec(Vec &&other) noexcept; // Move
@ -25,7 +26,8 @@ class Vec {
std::size_t size() const; std::size_t size() const;
std::size_t capacity() const noexcept; std::size_t capacity() const noexcept;
void push_back(const T &value) noexcept; void push_back(const T &value); // May except
void push_back(T &&value);
void pop_back() noexcept; void pop_back() noexcept;
void clear() noexcept; void clear() noexcept;