Currently implementing a .ini config file parser and writer and generator. I'm using the mINI project as the initial source code. I have to change that project because:
1. It's not using allocators
2. Namespace
3. Coding Style
4. Doesn't match my initial thought on how it should be
5. Doesn't match the C++20 concepts that I need to match the other config file types.
More info: https://github.com/the-moisrex/webpp/issues/85
1. It's not using allocators
2. Namespace
3. Coding Style
4. Doesn't match my initial thought on how it should be
5. Doesn't match the C++20 concepts that I need to match the other config file types.
More info: https://github.com/the-moisrex/webpp/issues/85
GitHub
INI config · Issue #85 · the-moisrex/webpp
.ini config file manager support. The initial source is from: https://github.com/pulzed/mINI
Okay, I've got the basic LRU Cache working so far. Plenty of work to be done including:
- Making Parent Storage Gate work.
- Implementing File Gate
- Implementing common cache algorithms
- Adding Expired LRU and other Cache Strategies.
Storage Gates:
These are the ways that the cache can be stored. For example, in memory with std::map, or in a JSON File.
These also can have a parent storage, for example our memory cache can have a file cache as a parent which it means if the memory is not enough, it'll use the parent cache instead of removing it.
Cache Strategies:
These are the ways that the cache is strategiezed. for example, LRU is the Least Recently Used and will remove the caches that you haven't used much. But there are other strategies, for example we could have a strategy that will remove the caches based on the time of access.
Let me know if you're interested in implementing these with me. It's gonna be pretty fun.
- Making Parent Storage Gate work.
- Implementing File Gate
- Implementing common cache algorithms
- Adding Expired LRU and other Cache Strategies.
Storage Gates:
These are the ways that the cache can be stored. For example, in memory with std::map, or in a JSON File.
These also can have a parent storage, for example our memory cache can have a file cache as a parent which it means if the memory is not enough, it'll use the parent cache instead of removing it.
Cache Strategies:
These are the ways that the cache is strategiezed. for example, LRU is the Least Recently Used and will remove the caches that you haven't used much. But there are other strategies, for example we could have a strategy that will remove the caches based on the time of access.
Let me know if you're interested in implementing these with me. It's gonna be pretty fun.
Cache Directory:
In process of implementing caches in webpp project, I can now introduce "directory cache". It lets you store each key/value pair in a file of its own inside a specified directory.
This cache directory is a "Storage Gate" and thus witch conjuction with a Strategy, you can get more useful stuff out of it.
Example of cache names:
16780311998597636082-16780311998597636082.v1.0.0.cache
4939359993625789802-3.v1.0.0.cache
4939359993625789802-1.v1.0.0.cache
4939359993625789802-4.v1.0.0.cache
4939359993625789802-2.v1.0.0.cache
4939359993625789802-5.v1.0.0.cache
Don't worry, each part of the name is there for a reason.
We've got name of the cache at first (hashed)
Then we've got the hashed key (using std::hash not md5 or other hasing functions)
Then the version of the directory_gate
Then the extension (which is customizable)
Next step I need to work on the "cache" type itself and make sure that it implements all the needs of the final user (you hopefully).
And also I need to implement Parent Storage Gate. Parent gate is a Storage Gate that gets passed to another Storage Gate as a template type. This way, we can for example do this:
We can have a memory_gate<directory_gate> which essentially means I want to store my caches in memory but when the memory is not convinient, I want them to be backed up or stored as files.
In process of implementing caches in webpp project, I can now introduce "directory cache". It lets you store each key/value pair in a file of its own inside a specified directory.
This cache directory is a "Storage Gate" and thus witch conjuction with a Strategy, you can get more useful stuff out of it.
Example of cache names:
16780311998597636082-16780311998597636082.v1.0.0.cache
4939359993625789802-3.v1.0.0.cache
4939359993625789802-1.v1.0.0.cache
4939359993625789802-4.v1.0.0.cache
4939359993625789802-2.v1.0.0.cache
4939359993625789802-5.v1.0.0.cache
Don't worry, each part of the name is there for a reason.
We've got name of the cache at first (hashed)
Then we've got the hashed key (using std::hash not md5 or other hasing functions)
Then the version of the directory_gate
Then the extension (which is customizable)
Next step I need to work on the "cache" type itself and make sure that it implements all the needs of the final user (you hopefully).
And also I need to implement Parent Storage Gate. Parent gate is a Storage Gate that gets passed to another Storage Gate as a template type. This way, we can for example do this:
We can have a memory_gate<directory_gate> which essentially means I want to store my caches in memory but when the memory is not convinient, I want them to be backed up or stored as files.
I was looking into Sphinx, ReadTheDocs, Pandoc, and even man pages to see which ones are the best for me.
Now I'm thinking, instead of writing the the whole thing in a different formats and weird syntax and even let other websites access my github repos... I just don't want all of these. I want something simple, that everybody can afford.
So maybe I thought why not my own website and I use my own webpp framework to make it, and then I thought, well, I don't want to pay for that just yet (I probably will though).
So now I'm thinking why not add a feature to the webpp that instead of CGI, and Boost, I make something that generates all the website.
Implementation Choice:
There are numerous ways I can make this happen:
1. Making a new Protocol in webpp
2. Adding it to the SDK that goes and runs all the routes and generates the html files.
3. Convert the back-end website into a front-end webassembly website.
A new Protocol
Writing C++ code just to produce html static files seems way too complicated.
In the SDK
The second one seems like it's already implemented by wget and other tools that recursively traverse the website and save and change the links.
Maybe I could do that in a much better way?
As a webassembly website
Since I haven't yet started adding features for front-end, I'm not really sure how hard it is to implement such a thing. But it's an amazing idea actually.
See the disscusion on GitHub.
Now I'm thinking, instead of writing the the whole thing in a different formats and weird syntax and even let other websites access my github repos... I just don't want all of these. I want something simple, that everybody can afford.
So maybe I thought why not my own website and I use my own webpp framework to make it, and then I thought, well, I don't want to pay for that just yet (I probably will though).
So now I'm thinking why not add a feature to the webpp that instead of CGI, and Boost, I make something that generates all the website.
Implementation Choice:
There are numerous ways I can make this happen:
1. Making a new Protocol in webpp
2. Adding it to the SDK that goes and runs all the routes and generates the html files.
3. Convert the back-end website into a front-end webassembly website.
A new Protocol
Writing C++ code just to produce html static files seems way too complicated.
In the SDK
The second one seems like it's already implemented by wget and other tools that recursively traverse the website and save and change the links.
Maybe I could do that in a much better way?
As a webassembly website
Since I haven't yet started adding features for front-end, I'm not really sure how hard it is to implement such a thing. But it's an amazing idea actually.
See the disscusion on GitHub.
GitHub
Static website generator · Issue #102 · the-moisrex/webpp
I was looking into Sphinx, ReadTheDocs, Pandoc, and even man pages to see which ones are the best for me. Now I'm thinking, instead of writing the the whole thing in a different formats and...
With this, you can check the constraints of a function call arguments inside a C++20 requires clause.
I've been looking for such a thing for a long time until I saw this tweet; I then updated it to what you see in the picture and I also added it to my web framework.
Example Usage:
Source on GitHub
My updated version on Godbolt
Initial idea on Godbolt
I've been looking for such a thing for a long time until I saw this tweet; I then updated it to what you see in the picture and I also added it to my web framework.
Example Usage:
template <typename T>
concept fooable =
requires(T t) {
t.foo(
requires_arg(std::integral),
requires_arg(std::same_as<short>)
);
};
Source on GitHub
My updated version on Godbolt
Initial idea on Godbolt
With this, you can pass concepts as a template parameter easily.
Source code on Github
Example on Godbolt
Source code on Github
Example on Godbolt
Web++: A C++ Web Framework
I changed the license to MIT.
Should I change the license to BSL? What do you think?
This media is not supported in your browser
VIEW IN TELEGRAM
Here's a couple of days of me working on this project using Termux on Android. I've got 3 months of these now.
I've been recording them using asciinema and what you see above is merely a replay of them.
I've been recording them using asciinema and what you see above is merely a replay of them.
😁1
alloc_deleter in boost smart_ptr is not move assignable,
thus std::unique_ptr<T, alloc_deleter> is not,
thus variant<..., unique_ptr<..., alloc_deleter>> is not,
thus vector<variant>::emplace(iter, ...) can't move stuff around!
Should alloc_deleter be move-assignable?
The tweet
thus std::unique_ptr<T, alloc_deleter> is not,
thus variant<..., unique_ptr<..., alloc_deleter>> is not,
thus vector<variant>::emplace(iter, ...) can't move stuff around!
Should alloc_deleter be move-assignable?
The tweet
Web++: A C++ Web Framework
alloc_deleter in boost smart_ptr is not move assignable, thus std::unique_ptr<T, alloc_deleter> is not, thus variant<..., unique_ptr<..., alloc_deleter>> is not, thus vector<variant>::emplace(iter, ...) can't move stuff around! Should alloc_deleter be move…
The story went on to the point that I made a template new type called "dynamic" which is an allocator-aware type.
The problem that I got with it right now is that where I tend to use that type is where the 1th template parameter will be an incomplete type.
That led me to adding checks to see if a type is_complete. But now I don't think that's the right solution here.
I found a compiler bug along the way too.
The problem that I got with it right now is that where I tend to use that type is where the 1th template parameter will be an incomplete type.
That led me to adding checks to see if a type is_complete. But now I don't think that's the right solution here.
I found a compiler bug along the way too.
Implemented my own std::function alternative (which is allocator-aware) called istl::function and it's beating std::function's performance with the default std::allocator.
Read more about its performance here
Read more about its performance here
✔️ SQL Query Builder tests are passing
✔️ istl::function tests are passing
1. Next steps are to write more tests for SQL Query Builder and then solve them of course so we can have a more stable SQL Database support system inside this.
2. After that, I might start working on a new, dynamic router. The current router is static and it's good but you probably can't use it inside a source file and thus that would mean your whole application essentially will have to be a big header-only executable. So a dynamic router is necessary.
I probably will use the recently made
✔️ istl::function tests are passing
1. Next steps are to write more tests for SQL Query Builder and then solve them of course so we can have a more stable SQL Database support system inside this.
2. After that, I might start working on a new, dynamic router. The current router is static and it's good but you probably can't use it inside a source file and thus that would mean your whole application essentially will have to be a big header-only executable. So a dynamic router is necessary.
I probably will use the recently made
istl::function in there too.
Web++: A C++ Web Framework
Implemented my own std::function alternative (which is allocator-aware) called istl::function and it's beating std::function's performance with the default std::allocator. Read more about its performance here
Some of istl::function properties so far:
- allocator-aware
- Small stack size (alloc size + void*)
- no internal SOO, you can use stack_allocator instead
- beats std::function at benchmarks, and gets beaten by it at the same time
- allocator-aware
- Small stack size (alloc size + void*)
- no internal SOO, you can use stack_allocator instead
- beats std::function at benchmarks, and gets beaten by it at the same time