#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <initializer_list>
#include "index_iter.h"
#include "list.h"
#include "linked_list.h"
int main() {
auto l = List<int>{ 7, 3, 2 };
#if 0
printf("C Style\n");
for (size_t i = 0; i < l.count; ++i) {
auto value = l[i];
printf("%zu: %i\n", i, value);
}
#endif
#if 0
printf("Iterator in C style loop\n");
auto iter = l.index();
auto begin = iter.begin();
auto end = iter.end();
for (auto it = begin; it != end; ++it) {
auto [value, i] = *it;
printf("%zu: %i\n", i, value);
}
#endif
#if 0
printf("C++ Iterator\n");
for (auto [value, i] : l.index()) {
printf("%zu: %i\n", i, value);
}
#endif
#if 0
printf("C++ Iterator without index\n");
for (auto value : l) {
printf("%i\n", value);
}
#endif
#if 1
auto list = Linked_List<int> {934, 482, 349, 832};
list.reserve(5);
list.add(91);
list.add(82);
list.add_range({123, 421, 999});
#else
auto list = Linked_List<int> {};
list.add(73);
list.add(52);
list.add(98);
list.add(23);
list.add(91);
list.add(82);
#endif
#if 1
printf("Linked list\n");
for (auto value : list) {
printf("%i\n", value);
}
#endif
#if 0
printf("Linked list with index\n");
for (auto [value, i] : list.index()) {
printf("%zu: %i\n", i, value);
}
#endif
#if 0
printf("Linked list ptr\n");
printf("%p\n", &list.first->elements[0]);
printf("%p\n", &list.first->next->elements[0]);
for (auto ptr : list.iter_ptr()) {
printf("%i, %p\n", *ptr, ptr);
}
#endif
#if 1
printf("Linked list ptr with index\n");
printf("%p\n", &list.first->elements[0]);
printf("%p\n", &list.first->next->elements[0]);
for (auto [ptr, index] : list.iter_ptr().index()) {
printf("%zu: %i, %p\n", index, *ptr, ptr);
}
#endif
#if 1
printf("Linked list indexing\n");
printf("%i\n", list[0]);
printf("%i\n", list[1]);
printf("%i\n", list[2]);
printf("%i\n", list[3]);
printf("%i\n", list[4]);
printf("%i\n", list[5]);
#endif
list.release();
return 0;
}
template<typename Value>
struct Index_Iter_Value {
Value value;
size_t index;
};
template<typename Value, typename Iter, typename End>
struct Index_Iter {
Iter iter;
End iter_end;
size_t index;
Index_Iter begin() {
return *this;
}
End end() {
return iter_end;
}
Index_Iter operator++() {
index += 1;
++iter;
return *this;
}
bool operator!=(End other) {
return this->iter != other;
};
Index_Iter_Value<Value> operator*()
{
return Index_Iter_Value<Value> { .value = *iter, .index = index };
};
};
template<typename T, typename Iter, typename End>
Index_Iter<T, Iter, End> index_iter(Iter iter, End iter_end) {
return Index_Iter<T, Iter, End> {
.iter = iter,
.iter_end = iter_end,
};
}
template<typename T>
struct List_Iter {
size_t count;
T *elem;
size_t index;
List_Iter<T> operator++() {
index += 1;
return *this;
}
bool operator!=(size_t end_index) {
return this->index != end_index;
};
T operator*()
{
return elem[index];
};
};
template<typename T>
struct List {
size_t count;
size_t capacity;
T *elem;
List(std::initializer_list<T> list) {
count = list.size();
capacity = count;
elem = 0;
if (count == 0)
return;
elem = (T *)calloc(capacity * sizeof(T), 1);
size_t i = 0;
for (T e : list) {
elem[i] = e;
i += 1;
}
}
void add(T v) {
if (elem == 0) {
capacity = 4;
elem = (T *)calloc(capacity * sizeof(T), 1);
} else if (count >= capacity) {
size_t new_capacity = capacity * 2;
T *new_elem = (T *)calloc(new_capacity * sizeof(T), 1);
memmove(new_elem, elem, count * sizeof(T));
free(elem);
elem = new_elem;
capacity = new_capacity;
}
elem[count] = v;
count += 1;
}
T& operator [](intptr_t i) {
assert(i >= 0 && "index is negative");
assert(i < count && "index is out of range");
return elem[i];
}
void release() {
free(elem);
elem = 0;
count = 0;
capacity = 0;
}
List_Iter<T> begin() {
return List_Iter<T> {
.count = count,
.elem = elem,
.index = 0,
};
}
size_t end() {
return count;
}
Index_Iter<T, List_Iter<T>, size_t> index() {
return index_iter<T>(begin(), end());
}
};
template<typename T>
struct Linked_List_Link {
Linked_List_Link<T> *next;
uint32_t count;
uint32_t capacity;
T elements[0];
};
template<typename T>
struct Linked_List_Iter {
Linked_List_Link<T> *link;
uint32_t index;
Linked_List_Iter<T> operator++() {
index += 1;
if (index >= link->count) {
index = 0;
link = link->next;
}
return *this;
}
bool operator!=(bool stub) {
return link;
};
T operator*()
{
return link->elements[index];
};
};
template<typename T>
struct Linked_List_Iter_Ptr {
Linked_List_Link<T> *link;
uint32_t index;
Linked_List_Iter_Ptr<T> operator++() {
index += 1;
if (index >= link->count) {
index = 0;
link = link->next;
}
return *this;
}
bool operator!=(bool stub) {
return link;
};
T *operator*()
{
return &link->elements[index];
};
};
template<typename T>
struct Linked_List_Iter_Ptr_Container {
Linked_List_Link<T> *first;
Linked_List_Iter_Ptr<T> begin() {
return Linked_List_Iter_Ptr<T> {
.link = first,
.index = 0,
};
}
bool end() {
return false;
}
Index_Iter<T *, Linked_List_Iter_Ptr<T>, bool> index() {
return index_iter<T *>(begin(), end());
}
};
template<typename T>
struct Linked_List {
size_t count;
Linked_List_Link<T> *first;
Linked_List_Link<T> *last;
Linked_List(std::initializer_list<T> list) {
count = 0;
first = 0;
last = 0;
if (list.size() == 0) {
return;
}
reserve(list.size() > 4 ? list.size() : 4);
// add_range_reserved ?
add_range(list);
}
void add(T v) {
add_range({v});
}
void add_range(std::initializer_list<T> list) {
size_t reserve_count = list.size();
if (reserve_count == 0) {
return;
}
reserve(reserve_count);
auto link = last;
for (T e : list) {
if (last->count >= last->capacity) {
last = last->next;
}
last->elements[last->count] = e;
last->count += 1;
count += 1;
}
}
void reserve(size_t reserve_count) {
if (reserve_count == 0) {
return;
}
auto link = last;
if (link == 0) {
auto allocation_size = (size_t)&((Linked_List_Link<T> *)0)->elements + sizeof(T) * reserve_count;
first = (Linked_List_Link<T> *)calloc(allocation_size, 1);
first->capacity = reserve_count;
last = first;
link = first;
} else {
intptr_t reserve_counter = reserve_count;
while (link->next != 0) {
reserve_counter -= link->capacity - link->count;
link = link->next;
}
reserve_counter -= link->capacity - link->count;
if (reserve_counter > 0) {
auto new_link_capacity = count > (size_t)reserve_counter ? count : (size_t)reserve_counter;
auto allocation_size = (size_t)&((Linked_List_Link<T> *)0)->elements + sizeof(T) * new_link_capacity;
link->next = (Linked_List_Link<T> *)calloc(allocation_size, 1);
link->next->capacity = new_link_capacity;
link = link->next;
}
}
}
T& operator [](intptr_t i) {
assert(i >= 0 && "index is negative");
assert(i < count && "index is out of range");
auto link = first;
while (i >= (intptr_t)link->count) {
i -= link->count;
assert(link->next != 0 && "index is out of range");
link = link->next;
}
return link->elements[i];
}
void release() {
auto link = first;
while (link != 0) {
auto next = link->next;
free(link);
link = next;
}
first = 0;
count = 0;
}
Linked_List_Iter<T> begin() {
return Linked_List_Iter<T> {
.link = first,
.index = 0,
};
}
bool end() {
return false;
}
Index_Iter<T, Linked_List_Iter<T>, bool> index() {
return index_iter<T>(begin(), end());
}
Linked_List_Iter_Ptr_Container<T> iter_ptr() {
return Linked_List_Iter_Ptr_Container<T> {
.first = first,
};
};
};