This video demonstrates how to implement a routing system in a custom file system using path pattern matching, inspired by Express.js routing syntax. The developer shows how to define URL-like paths with parameters (e.g., `/latest/{id}`), split paths into components, and match them against predefined templates to extract parameters and resolve file locations. The implementation involves creating string splitters to break paths, pattern matching algorithms to compare path components, and hash maps to store and retrieve parameter values. This approach enables building flexible file system interfaces where paths can represent multiple files based on parameter values, similar to how web frameworks route HTTP requests to different handlers.
Deep Dive
Voraussetzung
- Keine Daten verfügbar.
Nächste Schritte
- Keine Daten verfügbar.
Deep Dive
operating system development - filesystemHinzugefügt:
Heat. Heat.
Hello everyone.
Today is an exciting day. Today we kill JavaScript.
Today we kill NodeJS.
Today we killed ExpressJS.
So be excited about that. After today there will be no more JavaScript, no more Node, no more mpm, no more supply chain attacks, uh no more slop, no more AI, no more I don't know, just insert buzzwords.
Uh, React. Oh, also React is dead.
C-pilot don't have to do anything to kill co-pilot.
Come on.
Come on.
Let Let the old man just like live out his last few days.
Oh, old man.
mic. Wait, hold on. I don't know what changed. I don't remember moving my monitors at all. But did I just move? I also did a move, but somehow now this monitor is covering a little bit of this monitor, which means I can't read the chat fully. And again, I don't remember actually moving anything.
All right, that's better.
How many lines of code? That's a good question.
56,000 195.
Microsoft didn't get rid of Copilot from Notepad. They got rid of the name Copilot in the icon, but now it's writing tools. Yeah. No, no, no. I don't remember if I saw it myself or I I saw it in an article or something, but yeah, I remember they did that.
It's uh not co-pilot. It's sparkling chat GPT.
It's only copilot if it comes from the co-pilot region of France.
As if France couldn't as if France wasn't bad enough already. Sorry, French people. I actually like your country.
I'm just European and contractually obligated to make jokes about it.
Okay. So what do I mean by killing JavaScript NodeJS and ExpressJS?
It means I am going to take something that I believe to be a great idea that Express has created and implemented in my operating system and uh nothing's going to happen to them.
And you should not use this to um write servers. So unfortunately, they're going to be alive and well.
I don't understand what it is, but only when I stream, I need a fan on. I can live the entire day without a fan, but when I stream, I need the fan on.
I did a test once with Google. I searched GPT and it took me about seven or eight pages to get to a Wikipedia page which link to think that GPT might mean which includes GUID partition table.
uh the program to count lines is just the script.
I need to remember to not open micro from within zed.
See, it was easier for me to just type type in micro count to show the one line. Uh to be fair, I could have also done cat count and would have shown like this, but it was easier for me to do it. But then to close micro, you do control Q, which also closes zed. So I need to remember not to do that.
GPT chat jeopardy is your AI chatbot for everyday use.
Chat with the most advanced AI to explore. Citation needed to explore ideas. Citation. Well, no. Okay, I'll give you that one. Solve problems.
Citation needed and learn faster.
Citation needed. GPD5 is here. Oh, we transform.
Wait, so in Spanish it's actually a TGP except Okay. Yeah, this is actually a natively Spanish page.
Again, no matter how many times I tell Google, hey, give me results in English, it will never do that.
What is GPT and how does it work? Chat GPT apps on Google Play. Introducing Chat GPT. Chat GPT 5.5.
What is it? Okay, here it is. What's the one two three four five six seven results of marketing before you get well okay uh this may not count as marketing I don't know to be fair if you're looking up GPT most likely you're looking for chat GPT even if you're looking for something else that uses the same architecture they don't use GPT in their name um the only exception being if you're actually looking for a partition table thing.
Oh, the Wikipedia page for something that has multiple meanings.
Holy [ __ ] we're getting to some websites that get zero hits.
If I click on them, their servers, their server usage is going to go like this.
I'm not seeing it here at all.
The chat GPT page of Wikipedia is here.
Uh, the English version of the IBM page that I got before in Spanish is here, GPT3, GPT40.
That's nostalgic to a lot of people.
It's like seeing an X.
Like like literally.
Yeah. No, this is Oh, here it is. Well, no.
Yep. Here it is in Spanish in page 10. So, we got to the Google.
That's how far you have to go to actually find that.
Why do I have this open? What is this?
Interesting website.
I think it has something to do with PZIX.
All right, here's what I'm actually going to do today. Again, I'm I'm going to steal an idea from Express.js, which essentially means scaling Express, Node, and uh um JavaScript. At least if you, you know, follow AI hype marketing rules.
you copying something is the same as ending it.
So, um over the past few weeks, I've been working on my file system and yesterday and the day before, essentially this weekend, I've been building um a few interesting features to the file system like aliases and uh transformations.
So aliases are just sim links or links essentially where you know a file just points to another file. Accessing this file gives you information from that file.
Kind of simple. Um I had been saying that um aliasing on Linux required you to always resolve it before you could access the data. That's not true.
I think that's true of 9P which is the protocol that uh QIMU uses to communicate between host and guest operating system. Um in that case it's true but in Linux it's not. Yesterday I just did a little simple uh libby Linux very simple couple of lines u test with a sim link and you can access it without having to resolve anything. So I think um just the fact that I was doing everything through 9P led me to believe that but I was wrong.
But that is also how it works in my system. You just talk to a file and that file links you to another file but you don't you don't have to worry about that. You talk to it and it automatically forwards all the data.
And uh then I also added transformations is a bit of a strong word. That's how it's meant to be used but it's not really what it does.
Um, I essentially added things that can override the default behavior of the file system for specific files. So in when you read this file, instead of running the default function for reading a file, you run this other function instead.
And I used all that to build the infrastructure for an LSP which I ended up calling I don't like the name. So, I always say I don't like the names that I come up with and then I never change them for anything better.
So, for now, it's just going to be called the language file system protocol as opposed to the language server protocol, which is what most code editors use, right? So I used it to build this thing where um you talk to this folder.
All right. So the example of what I'm going to explain is actually here, but just cover your eyes real quick. All right. So you talk to lang. Well, the first thing you're supposed to do, which right now is kind of hardcoded. There's no ability to do this binding yet. You go to you want to bind your software project that you want to get syntax highlighting formatting autocomplete for all of that stuff. You bind the root folder of the project to this folder and then you know if you try to access anything inside this folder like a main. C file then you will find the actual main.c C file again mirrored to where your real project is.
But thanks to these transformations which are really just overrides, I can do language syntax main. C and reading this file will give me syntax highlighting information for this file.
Essentially this file is just linked to this file which itself is linked to the real file wherever that might be in your project structure.
Um but instead of reading it normally it reads it and then passes this through you know a parser that gives you syntax highlight information and then it returns that. Now there's no actual parser yet. Um, so by parser that gives you syntax highlighting information, I mean a for loop that looks for include and highlights it in yellow, but it works. It It's supposed to show the architecture of the of this whole system. Uh, we'll get to the syntax highlighting part eventually, but we're not there yet.
Uh and essentially the way that it does that is it overrides the read function for this file or actually for any file inside of this folder. Instead of calling the normal read function which just reads the file, it calls another read function which reads the file and then passes through um a syntax highlighter and then returns you the result of that. That's why I call them transformations. They're meant to transform the data from the file, but in reality, all they do is just overwrite the default behavior.
Right? The problem that you can see with this is that you can only have one project um getting syntax highlighting at the same time. If you look at what I have right now, I have two projects open plus qimu on this thing. Sometimes I can work with up to like five different projects open with different uh like for example I have a game game engine UI library that the game uses um shared library my own libcy um replacement and uh that's it. So four projects open at the same time. Sometimes I can have more and I should be able to get syntax highlighting, autocomplete and all that stuff from all of them. But here we can only have one.
And also there's technically no differentiation between different programming languages.
uh which maybe you could get around but honestly it's not great. So in reality the way that I would want to do this is language then specify the language that I want to talk to talk about which is C and then specify a project ID so I can have multiple projects open at the same time just refer to them by their ID. So let's say that this one is ID one right? So I saw I I can talk to this or maybe I can simplify it and just like the project ID already tells me which language it's supposed to be or whatever. The point is I want to have some sort of parameters to these file paths. I I keep wanting to call them URLs because it's very similar to how URLs work, which is why I'm taking inspiration from uh NodeJS, but they're not. But of course, URLs have very much already dealt with this kind of stuff and uh very much already come up with great solutions to this, right? Right. So ExpressJS is one that I know about. I don't know about any others actually. I've only done very little backend code mostly in Node. Unfortunately, I know we all have a shameful past that we are um that we would rather leave buried.
However, I am brave enough to talk about it openly.
I have used node in the past.
Full disclosure.
And uh express is what I used to do routing.
It allows you to do exactly what I'm saying with this syntax.
Pardon me for using node or for admitting it. I'm hoping it's for the second one.
I like the syntax. I have to say admitting fair.
It's good. Uh they they have some examples here. So essentially the way that you use um express it allows you to just route different endpoints um to different functions, right? So different parts of your API or whatever you're building um do different things.
A shocking concept I know.
So if you call if you do a get request to the root which is to say the domain.com or whatever localhost port 3000 uh with nothing else after that and you do a get request on that which is to say you open it in your browser even then you get this. If you do a post then you get this instead or you can do it for all of them. So depending on what URL you're accessing and how you're accessing it, it routes you to different places. And uh the interesting part about that is the this kind of stuff. Now, I'm not sure how much stuff like this would be useful where you lowkey have regular expressions or are they like full regular expressions.
Oh, no. They no longer work.
Never mind.
Yeah, I I can't really think of a reason why you would want to do this.
Maybe maybe you want to do this, but I don't know.
Um, you can do it off of regular expressions.
Okay, so maybe they actually just replace these with these so it still work. But again, I don't know why you would want to do this.
But the part that I care about is the parameters where you can specify a route as users, then a user ID parameter, books, and a book ID parameter.
And uh it is matched by this thing here.
where again you have the semicolon being that's just a colon semicolon yeah that's just a colon where you have the colon being used to indicate this is a parameter with this name which then inside of here you can access I believe by doing rack params user ID maybe probably There's more examples of that.
And uh that's it terms of at least for this guide for routing. Uh that's all the functionality that they explain, but it is kind of what I want to build.
Yesterday I did a very simple kind of prototype for this very ugly code, but I'm actually I'm actually enjoying doing things like this where I essentially just like at the end of one uh I'm just going to see one screen. At the end of one stream, I do a quick and dirty prototype that's not actually supposed to be proper code. Maybe it works. Maybe it's great. and I commit it. But most of the times um I don't.
So yeah, just a quick simple type of um prototype for what I want to build and then the next stream I build it properly. Ideally doing some research or thinking things over a little bit in between.
kind of have but kind of want to do a little bit more research into this or I want to see what what other people are doing, right? Because this is what Express is doing. Um, plan 9 for example is another operating system that has a very powerful file system. They essentially do the same things that I want to do. I want to see if they have any kind of helpers for that for writing this kind of file system.
uh structure.
Um but yeah, that's kind of what I'm planning to build.
And again, yesterday I did a very simple type of um prototype which you define these um URLs So first off, you can access a directory as if it were a file. So it kind of has a hidden file in the root of the directory if you will. So you define that one and what it points to.
You can define uh a parameter called sort which is a directory. Then inside of sort there's ID going by parameters or just ID in the root directory which are files in the root directory. And essentially what I did is some very hard-coded logic to uh list the entries of this directory by just going through these entries and then whenever you find a semicolon that is a parameter that you need to resolve calling a function that's like hey we're being asked for um all the sorts which is just latest. You can only sort by latest right now, but if I add more, there could be more. And uh we're being asked for all the ids.
And if I'm not mistaken, I even got it to work where um the ids here are incremental ascending and here they are descending because it's sorted. Now the files don't actually open.
And that kind of requires slightly different logic or the opposite logic of what I have for this. But hold on, let me actually put something in the clipboard so we can test it. Here we go.
We have uh the directory as file which is indicated by this symbol. The latest which is the only type of sorting 0 1 and two. And then if you go inside of latest you can see 2 1 and zero which is the opposite order of um you know based on the sort right. Um so that is for listing out all the contents where essentially anytime you have a parameter you you just iterate through these and every time there's a parameter there's a helper function that tells you how to iterate over that parameter all the possible values that it can have.
um instead to open a file or to get information about a file or anything like that. It's kind of the opposite problem where you're given a fully resolved um URL with no parameters and you have to resolve it into which one of these is it and what each parameter's value is.
Right? So if I'm given a URL that's clipboard 3 that is this. So this is uh well this is stack file system but it's used to power clipboard. So clipboard is the root. Just ignore that part. If I have three then that's ID. If I instead have latest three then that's sort ID. Or if I just have latest it's just sort.
Um so very simple pattern matching shouldn't be too difficult except um there can be ambiguity in this system. For example, if I introduce a new type of parameter that's like I mean I guess I just shouldn't allow this type of thing. Um timestamp for example. This is a numeric value. This is also a numeric value. How do you tell the two apart?
And again, I probably should just not allow this type of thing.
But we kind of need to define the system that allows me to do the parsing and that allows me to, you know, prevent these types of things from happening doing the URL routing properly and maybe write yesterday's code a little bit better.
All right. How did you learn C such a s deep level? Just write in it. Just write it and then you write more and then you write more and then you write more.
Watching from Kenya. Nice.
All right. So, uh that is what I'm planning to do. But again, before I even do it, I kind of want to look into how plan 9 does it.
Cuz again, I technically don't need all of this to build, for example, the language thing to work. Like I said, I could just make it hardcoded, right? I could define an entry called C and an entry for each language and just you know always parse some um hold on that doesn't make a lot of sense. Always parse something.
Actually I am already doing this so maybe it's better if I just show it where uh you can do slashprock slash three slash state which gives you the state of process 3. And that's essentially the same as this thing just manually.
But um I'm doing the parsing manually per each kind of URL path I expect to find. The first thing I expect to find is always an ID. So I parse it manually as an ID.
Then after that, I expect to find what I'm trying to do, whether it's state or um out, which is the output of the process. The only two files that I currently support.
But this won't scale too well, right? If you try to build something a little bit more complex, it's going to become a problem.
So much better to have helpers to do this.
anonymous followed your channel.
Um, and again, I I I like this way of doing it. So, we're going to do it like that. Now, again, we have a couple things to answer. First off, just looking at this, this is all relative to the root directory, right? So all of these are root directory entries.
We have to make sure that there's no ambiguity between them and we have to know how to parse them.
Both of these things should be the same, but I kind of don't know how to do it.
Keep in mind we're working with C which is a system that doesn't have any kind of reflection or any kind of type typing even has a very basic type system cuz I could easily just be like the parameters for this parameters for this are sort which is an integer and I no sort which is a string and id which is an integer or even sort which is an enum right but if I do any of this all of it has to be manually done because we don't have this type of logic we don't have this type of capability inside of C but I like working with C I've been working on this for about a year now a little over a year file system April essentially. All right. So, yeah, I kind of want to take a look at what plan N is doing for this because again, plan N is another is where I took the inspiration for making my um file system have all these features.
Am I missing a bunch of virtual machines here or did I just delete them? I think I deleted them. I had a bunch of virtual machines that I wasn't using anymore. All right. So, I have a plan 9 VM.
Temple S is also there. Yes. And hell and haiku.
Um I know plan 9 has its own source code. So we can It does, doesn't it? Maybe insis.
Uh, yep. SRC.
All right. It should be something like lib fs. No, doesn't look like it.
Um, let's see. lib string oserve AVL bin bio C complete control disc drawate plate frame geometry HTML httpd bip blex No wait that wrong IP lex mach mammraw mamm layer mp ndb which by the way I want to look at this at some point it's a network database it's called uh network database because it was used to hold network information but also plan 9 is a distributed operating system so I guess it technically works over a network I kind of want I look at it. That seemed interesting. Also, I want to look into databases at some point or another. Uh, we got regular expressions, plum, scribble, sack, std, io, sunup, thread, venti, and uh, nothing specific to the file system, which is interesting again considering this is a very file system heavy operating system. So, maybe it's inside of nine.
[ __ ] I I don't know.
Does this I find?
Nope.
Maybe I shouldn't have done this from within the system itself.
KW. What's KW?
Oh, LSD is probably not what I'm looking for.
All right.
All right. Plan N. Um, thank you, but probably better off looking for this outside of you.
They do have their own actually standalone plan 9 file server.
So, hi MX.
Um, block devices, cache, warm driver, sync, copy, warm processes, whatever.
Not entirely sure where you're going with this plan. Now, um, file system has aliases, can override functions for specific files, which allows me to like do what I call transformations, but it's frankly a little bit the strong word.
Well, it depends on how you use them. It can technically power an LSP, just doesn't have a very good one behind it.
And um yeah, today I'm trying to do routing like this.
But I'm trying to look at if plan 9 has any kind of um stuff like this because again, plan N could very much benefit from this.
But maybe I don't know own declarative framework. Uh mine is not super declarative. I want to make it have declarative syntax in my own programming language, but since I don't have that right now, um yeah, it's not declarative, but yeah, I kind of went for hybrid cuz for C, I needed to not be declarative, but I kind of want it to be um I find UI to be more declarative.
Like, let me do an example of that.
you declare it just inside of a function. In reality, it's just calling this function. That's it. Which um internally just like creates um nodes automatically. It's a little bit [ __ ] the way that it does, not going to lie, but I guess it works.
All right.
Um, no idea how to look for what I want.
uh in the last few weeks of writing file systems I of the root that there were many things I'm reinventing every single time can make great use of the P9 file interface create file file trees file trees that's an interesting concept but other file systems need to be more detailed control and more flexibility using the standard P9 library which results in a lot of boiler plate code.
Okay. So, as far as what I'm looking for, it doesn't really help that they're saying, "Oh, I made a generator for it."
because it kind of means there's no way of doing this properly.
But might as well look at what they're doing.
I think it just kind of shows that there's uh no Okay, this is kind of what I'm talking about. Actually, the fact that they have a generator means that yeah, plan 9 doesn't have any kind of helpers for it, which is why this person made their own.
But I don't really want that. I want actually like resolving the path.
Like I don't want it at compile time or anything like that. I want it at runtime.
It's not that difficult.
Just a little bit of parsing.
Okay. So, simple example. Path to my file is equivalent to Okay. I I was hoping that this was what I was looking for, but variables are transported to the file system code as char strings. Their name is defined in a path for each file root curly braces.
All right. So, kind of what I mean. Yes.
Okay. Um, so this kind of tells me plan N doesn't really have any solution for this. This person just built their own, which obviously does not help me cuz I'm trying to build my own. I was just trying to take inspiration from. If plan N had already come up with something different, but from what I see, it's very similar to what I want to build, just with that kind of weird syntax.
My Windows partition just randomly corrupted. Nice.
Windows has a little tendency to do that.
All right.
Uh so now I have to define a few rules for this.
Technically, um, doing it like this kind of makes things more complicated, but do I really have a problem with that?
Yes, maybe I do.
Well, essentially Having it like this means that I need to define three different entries, three different templates and then I need to um differentiate between this param these two types of parameters which would mean I need to know when it's one or when it's the That's not That's not necessarily super difficult, honestly.
Might not have a problem with that cuz again I said uh maybe this one is string and this one is numeric. So that's how you tell them apart. But honestly, I can just create a function that checks what type of parameter it is and then or even just like checks is it this parameter yes or no just returns a boolean and that's it.
Maybe it can be that simple.
Then I don't have to deal with any kind of complex type systems and I can build a file system like this where um you don't necessarily have to sort.
Essentially, we're making this parameter optional.
The the other option would be to include this in here where you can do latest and then the ID or you can do um even ID3 something like this just to indicate default sorting. But no, or something like history, for example.
But I'm going to go with a no on that. I think I would much rather just have a function that's like, does it does this match this parameter? And that's it.
Okay. Now, what I do want to build is a separate file to no, not a folder, just a file to handle all this routing.
And uh yeah, just going to do that.
All right. So, just going to make it very hardcoded.
just a little test for the parsing and all that and then integrated into the file system cuz yeah everything I did here as a prototype is for the stack file system which relies on the virtual file system but it's meant for things that have some sort of history um like the clipboard which is the only thing that it's used for but it can be used for other things but technically I should have been doing it Here I just used this one as a prototype but now I want to do it properly. So uh how about we start with just a very simple test just again prototyping but a little bit more.
Uh, can I do?
I always struggle to build these structures, but can I do?
Will you have a problem if I do this?
Don't believe you will. Okay. So, I'm going to do ID actually four entries. Four entries.
this which is the I lost it directory as file.
Um sort and sort ID.
All right. So these are the four entries.
Then first I want to try listing them. So the same thing that I prototyped yesterday but done properly.
And then I want to try um parsing a URL to point it to the right thing here and also passing the parameters into that because that's kind of important.
All right. So let's start with the listing. That part is easy.
Hold on. Let me start building actual functions for this.
So, list directory contents is going to Can I make this like that.
I'm also going to make everything static because most likely I've already used the word entries although I'm going to make it test entries.
Uh static not test.
All right. Uh so list directory contents. Let me just start writing some boiler plate and then also some boilerplate for static void bars path recon RF print bars path. All right. So, we're just going to call these two functions.
List directory contents. We're going to try it with root. And then we're going to try it with latest.
And then we're going to try to parse um hold on few more tests that that latest and we're going to try zero which is supposed to match this. We're going to try also zero like this which is also supposed to match this.
Then we're going to try to parse the path just latest and also latest and also just one of the zeros really like that and like that.
All right.
Cool thing about it is since it's just string manipulation at this point, we can just put it in here.
Can I put an include inside here? That would be really funny.
It's not explicitly complaining. It is explicitly complaining.
All right, it let me do it, but then obviously it complained. But anyway, uh test routing.
Which one is not static buddy? What are you complaining about? Static declaration of list directory contents follows non-static declaration.
Does it does? Let me see if it runs.
Oh, it's literally already used. Even though I call this static, it's still a conflict. Also, it's going to complain about unused variable.
And here we have it. And actually, I'm going to panic after this.
No panic.
Just so we don't run anything else after that because we don't need it.
Two more hes actually.
Okay, perfect.
Uh so let's actually begin with this.
So for testing the entries um first thing I do and this one is going to be static inline char pointer um normalize a path.
Hello Ry, I'm doing good. How are you?
Um, which is essentially going to do if no path return zero.
Uh, if path equals to this thing, return path + 1. And otherwise, you just return path.
So we're essentially going to skip this thing, which is what I'm trying to test here.
Right? So all of these that currently say list contents of this and list contents of empty and list content of latest contents of latest just should all look the same now. Well, not really because they have different values, but the first two should look the same except I'm not calling this function. Oh my god.
Very clever.
See you.
All right, we're going to do the same thing here. Normalize the path. Path.
So indeed, it skips that part. Just latest 00 latest latest zero latest zero.
>> Skin biscuits followed your channel.
>> Cool.
Easy.
Should we actually return it as a string slice?
I want to do a test for how the function that I'm planning on using works. So, I want to use a split string split path using this character and then performing this function.
just to see how it handles this. Let's do a few more.
Um, latest zero.
Uh, just latest without that.
and then latest zero without the thing at the end. And then at the end of each of them, we're going to put some prints so we can check properly what each of them looks like.
All right. So, uh, for this one, it has an empty section and then latest with this at the end.
You're supposed to split by this character and you have this character at the end. That's clearly a bug.
Okay. So, I want to use this section that does this um not this section, this function that does string splits, but clearly it's doing it wrong because this you're supposed to split by this character. A character is not supposed to be there.
Uh, the string slice comes from here.
And I'm pretty sure I've literally had the same issue in other places. So that should fix it I believe from having fixed this issue several times.
Empty latest empty latest empty latest zero empty latest zero. Exactly.
All right.
Uh, cool. So, using this function is actually going to help me do what I'm trying to do particularly well, I hope. So, I can use it.
But we're going to do that after the adbreak since starting now. I'll be back in 3 minutes.
Heat. Heat.
Okay, we're back.
Not sure if it's a compliment or not that the music that I made is being called satisfactory music. I'm going to call it a compliment, but it is not satisfactory music. I have I played Satisfactory.
I think I have it in my wish list, but I don't think I've played it.
Okay, so we're going to do some routing.
Now I made this string split function which is supposed to Well, it's splitting all of these strings into these sections, which is exactly what I wanted to do.
Um, now there is one test I didn't do on it, which uh kind of breaks a little bit this one.
Yeah. Well, not really. Not really. Uh, I guess we're supposed to just ignore the initial empty one.
Now, about the string splitting thing, I need to use it to parse each of these elements of a I keep wanting to call them URLs. They're not each of the elements of the path individually uh while keeping track of which one it could possibly be looking at.
But uh function is a little bit uh lambda reliant. It relies on a on a function pointer.
So that is kind of not great for it.
Right?
Because what it does is it just runs this code and then just calls perform on it.
Can I just make it do the same thing but with a macro? It's not great, but it would help kind of inline this lambda because otherwise this is going to get a little bit complicated.
We're going to have this function which is going to have um essentially we're going to be doing lambdas and closures in C by hand.
All right, let let me see how it goes and then worry about it later. All right, let's begin with uh normalizing.
Oh, not normalizing.
Uh let's begin with I think I should do parsing first.
I'm not sure. Um, if I was using another language that doesn't expose its inner workings as much, I wouldn't have a problem with doing this. But I am using C and I am painfully aware of every allocation that happens when I do certain things. And because of that, it prevents me from wanting to do certain things cuz like how do I want to list the contents of a directory?
Keeping in mind the subdirectory that we're trying to list when I have a total number of entries here uh also high the way that I would do this is essentially by first parsing the subdirectory and then uh listing out the cont parsing the subdirectory to know which one of these I'm looking at and then um listing out the contents of that.
The problem is for example if the subdirectory is empty then the contents are literally all of this.
If the subdirectory is any of the sorts for example then the contents are this one's empty so this one wouldn't count but this one and let's say that for example we also have like a another entry here that has like I don't know /sort/hello/ ID these two entries which means um parsing a directory should return an array of entries that are possibly valid And this array is going to need to be allocated cuz we don't really have any nonallocatable way of even indexing into this array kind of um arbitrarily like say return the zeroth element and the second element. just return these two like some sort of uh array view array slice but with non-ontinuous elements is not a thing at least I don't think you can do that without also allocating that at the very least since it's an arbitrary number of of uh entries into that it does mean I need to have an an arbitrary arbitrary entries It sucks to do allocations. I don't like to do allocations. I hate allocations. I wish I never had to allocate anything in my life.
Unfortunately, I do.
I mean, I I can always create just like a um static array with as many elements as this. And that's going to be the worst case scenario where the array view that we're trying to look at is the same size as the array.
In which case actually that worst case scenario wouldn't even get to that point cuz it's just like one entry into it.
But whatever.
All right. The the point of this is in order to list the contents of a directory, first I want to parse the subdirectory to know which entries I want to list out.
So I'm going to work on that first on parsing first. So we're just going to disable all of this and we're just going to go for parsing instead.
again. I need to do array filtering here.
It's probably the easiest way that I can do this. If I was doing like this in a in a kind of uh functional programming language, I would just do test entries filter filter filter by I'm going to write it in kind of swift syntax cuz zero which is just like each of the entries um starts with the path segment that we're looking at or matches the path segment that we're looking And then even iterate over this array in order to do the listing.
But unfortunately again I can do this. I just have to have some sort of array um slice which requires allocation. And again, I'm just I'm just being a little [ __ ] about allocating.
Yeah. Well, I just have to do this.
All right.
There's two things I need to I need to consider. first off is splitting the string by using this character which I'm just doing with this function but it calls another function and that's not very se like that's not great but then also um the array entries into this I kind of wish at the very least I could write it like for each segment of path here for segment in path split that where we have some sort of iterator that is created by this function. How would I how would I build that? I kind of just feel like building that instead of actually building the the damn uh routing that I'm supposed to be building.
I could use a helper.
Okay, that I know how to build.
I could just have a type defctr um string iterator or string splitter which uses a seek character and then just keeps track of current.
Um Then a string split in place which takes a const char string. It doesn't return a void. It actually returns the string splitter helper chark.
And that's it.
or make string splitter.
Actually, let me put let me put it in its own little thingy.
Let me know. Let me know. Let me know.
Let me keep it here. Here is fine. Here is fine.
All right. So Just going to use these two functions real quick. I'm going to implement these two where to make a string splitter. It's literally just returning the original splitter with seek set to this thing.
Current set to STR.
No, current set to zero.
Uh, STR set to STR and pointer set to zero.
can even that I can line this.
Now for the splitter advance, this is where we do this logic.
Essentially, we do what what is currently inside of this loop one time at a time. That doesn't make any sense. One section at a time every time we call this function, right? So, uh some safety checks. First, we want to check that the splitter string exists and we want to check that the char exists. Otherwise, we're just going to return false.
No, the current location is splitter str plus splitter pointer.
That's where we currently begin which is at this point at the beginning of the string.
Then we get a new point which is taken from current using the splitters seeking character.
And if new point is equal to current then that means we didn't advance the string at all. Just return false.
Otherwise we do this calculation where point is actually just current.
We don't perform anything.
We are instead going to set the splitters current to this thing where the pointer we take from here, the cursor we take from here and the str is the splitter str with this size that we've taken from here.
Then the point does not get advanced. If we just advance the cursor, splitter pointer plus size + one.
And uh finally return true.
What is your problem?
It's conchar, isn't it?
Okay.
string splitter lib and C or string manipulation wouldn't know I always build my own things honestly that's the part that I like about C but honestly I hadn't even like identified that thing that I said before in another language like I showed the swift syntax that I would have written to solve this problem of like filtering this array that's probably doing a bunch of allocations that I don't even know about.
But now I'm actually painfully aware of the allocations that I'm doing.
So I try not to do.
Um All right. So shall we test it? The path parser.
Well, let me test it in this thing again actually.
So actually bring all these back.
Let me test it in this thing again.
But instead of calling the string split function, you're going to create a string splitter splitter from make string splitter from the path seeking this.
And then while Um, splitter advance using the splider splitter.
We are going to print next element.
I actually like doing it like this.
Helps me show empty elements as well.
splitter current end of string.
So we don't actually need to have this.
What?
Seriously, that's a God damn it. This is a C++ error where the order is not correct.
And uh this one is just an error from me using uh W error, which is that I'm not actually using this yet. So I have an unused variable, which is really annoying, but I don't want to have unused variables to be fair.
It's just annoying while you're prototyping and building stuff.
Okay. And let's see. We got uh empty latest empty latest empty latest zero empty latest zero empty latest zero empty latest no just uh latest zero. Now what's happening there in the second one?
This is one but this whole thing is a string.
What's happening here?
Yeah, the second element is just weird for some reason.
I don't get it.
Is there data in here already? It's reusing the same. No, cuz this should be very much returning a fully initialized thing.
This is zero initialized. This is Uh current.
I'm not sure why it's doing that.
I don't think the const did some weird memory stuff, but maybe nope.
I don't get it. I don't get what's what's happening here.
It's this one.
It's somehow parsing also this one.
Wait, why are we stuck here?
Okay.
Okay. I see what's happening. It's reading the next string after itself as well. And it it just so happens that because this string and this string were the same, they were this string wasn't actually there in the executable. It was just referencing this one. Which means that the next one was this one. And it was all being parsed together which means that just this function is not uh terminating correctly because this is the one that doesn't have uh an ending There.
All right.
This was supposed to be original.
this thing new this thing otherwise it's going to be completely incomprehensible.
All right slash latest slash comes latest slash and emits this element.
Then latest slash becomes empty and emits latest as an element.
Original empty new empty end of string.
Cool. That's correct because we're already at the end of the string. So new point is equal to current.
then okay this is the one we start at /l latest we emit just an empty element and continue with latest then we have latest we end up with an empty we emit latest and then we advance past it onto the next string.
Um cuz I'm not doing a check that I was kind of skipping. I kind of needed which is that if the splitter curse um pointer is bigger or equal to the splitter length then we're done.
And then just to be clear, if current equals to zero, we're also done.
That's interesting that it skipped into the next string.
I've had a few bugs where this happens cuz they're technically all all the strings are put together in the executable.
Um, kind of funny though. Okay, I think it worked this time. There's a little bit too much debug information to know.
Let's see. We start with empty latest empty latest empty latest zero empty latest zero latest zero.
Wonderful.
It works.
All right. So, we have a little in place string splitter which we can use now to test parsing some paths.
Going to bring you back.
We're going to get rid of this. We no longer this need this um lambda.
And wait, no. I meant to copy the code inside of this because I need it, but not this um parse path. Here we are.
And again, we actually don't need to uh normalize the path, which is to skip the original thing here.
Should be already handling that. And uh what did I don't need it anymore.
All right.
Uh starts with zero then empty zero.
Okay, that's good. We're also going to skip um Oh, why am I capitalized?
We're also going to skip anything where um it's empty, which already does that string normalization for us. So, we're checking zero zero latest latest zero latest zero.
Cool. All right. Um, now we're finally going to use these.
Oh, there's also a couple checks that I want to do for this and this.
Right. So again, I want uh an array view type of thing. something that allows me to check if an array not to check but to uh refer to specific elements inside of an array without allocating a subarray.
Um but either way for testing I need a couple more of these I'm going to have two more.
I don't know how to build this. All right, we're we're going to try to go just hardcoded right now. I smaller than 6 I ++ where we're going to try to access each of the test entries and compare it against that.
Going to also do a string quick split.
Oh, forgot the character.
All right. If there's no left hand side or no right hand side, then we're just going to return false.
Then left hand side is going to be this thing.
And uh we need the size of the string too.
the R length of str and if there is no size we're just going to return false as well.
Finally, right hand side of this thing is going to be the string slice where the data is going to be str + size and the length it's going to be full size minus size.
So, I'm going to use this one to just quickly split between Where are we? Like this and this string. Uh, I didn't expose that function.
Let's put it on here.
Then string quick split of the test entries I seeking this character on the left hand side and right hand side.
And if that succeeds, hello Kyle.
We're not even doing ASD parsing. We're doing some very basic parsing here, and it's already a lot.
Uh, but anyway, we're going to want to check if the left hand side matches the string that we're looking for.
Um, so that would be slice equal the left hand side and the current splitter.curren current insensitive found a match for V which is S where it's splitter current and test entries do I.
Now the worst part is this has to be a lot more complicated because this is left hand side, right hand side. But that's not even enough.
It's more recursive than this. But anyway, uh this should match this and this but not any of the others because those are parameters, which is what we do when we um when none of these match is we start checking parameters instead.
And none of them worked. Not a single one of them.
I think no split between empty and empty. Empty and empty. Empty and empty, which makes sense cuz there's no splitting before we get to this point. All right. Uh, if no left hand side, no right hand side. Yeah. If the string doesn't have a length. Yep.
Now, if the new point equals to the string or the new point is equal to zero. Okay. So, this part probably not.
Yeah, I'm actually checking for that here, not up there. That's probably why it failed constantly.
Okay. Found a match for this. Found a match for this.
So we found it.
Um But that's not enough. So what do we do in the case that you know we got these which are parameters.
Um, if left hand side has a length and whoops and left hand side data as a character equals to this symbol, then it's a parameter. We have to parse the parameter.
where we check that a string slice slice matches a parameter.
And this part is supposed to be kind of um hardcoded. We decide how to do this.
Um so if match param between the splitter current which is the part of the URL that we're looking for and the left hand side which is the part of the URL that we're comparing against then uh found a parameter parameter match for v which is this thing right where we got the splitter current and the left hand side.
Okay, so again this function should just be defined by me based on the value of the parameter that can be either ID well supposed to be an if statement just haven't actually started it as such and the other one which is what sort sort.
And if neither of those match, then we're probably not in a parameter, right? That makes sense.
All right. Um, so for sort, it's actually really easy.
We just return if the slice that we're comparing against matches the only possible sorting that we have right now. It can get more complex but honestly it's not part of this entire framework.
This is part of the implementation of the framework. This one is a little bit more complicated, but frankly not that much, where we just go through its characters and uh see if is numeric. Eric, it's what I want.
I don't have that function. So, real quick.
Oh, is digit. Okay, I do have that function. Let's just call different. If it's not a digit, then we return false.
Otherwise, we return true. And for the love of God, this is such an annoying thing.
The comparison between signed integers.
I can guarantee you that's never going to happen. Uh, I understand the the warning that this is an unsigned and this used to be assigned, but come on.
Right.
Let's see. Uh, so this matches, this matches, and these others do not.
So, one of these didn't work as I expected it to.
I'm assuming it's the parameter.
0 0 latest latest zero latest zero.
didn't even try to go into any of them.
Oh, wait. I just put this in the wrong place.
This supposed to be an else to this condition.
This condition is if we didn't manage to split.
Okay.
And indeed it does find some again. Now we have too many logs to know what the hell is going on.
All right. So uh this matches this matches.
Then zero matched ID zero matched ID latest matched sort latest match sort ID latest match sort latest match sort latest match sort.
Okay. So the individual matches are working. So it it can match latest against this and ID against this whatever this function which we will need to define um decides and uh really it'll be as easy as just forward declaring this function in the header in this header and then wherever we implement it you have to uh implement the function.
Hopefully, it's as easy as that. If not, I can do kind of what I did here with a virtual pointer function. But that either way, we can do it. All right.
Now, the logic that's a little bit off here is pretty sure really just about uh putting this loop outside of the other loop.
And then I don't even have to deal necessarily with um array slices or array views or anything complicated like that.
Right? So given an entire path, I compare it to each of the entries.
So without leftand sides but also doing this thing. So for the sake of simplicity let me write the whole thing again just copying a lot of code from here. So keep keep you around keep you around just returned.
All right. So, we're given a path. We want to parse it. We do this I smaller than 6 I ++.
And uh we actually probably want to return which path it matched.
So, a char pointer returning zero if none of them match.
Okay. Um, actually, we want to return something a little more complex. We want to return an entry, but right now we're working with strings, so it's fine. All right. So, we're going to want a string splitter to split the um template.
And we're going to make a string splitter for the current entry splitting by this. So we're going to evaluate each entry of this uh each element of those paths using the template split. And also if uh the splitter doesn't have a length then we're working with an empty like if at the beginning there's a slash and we can just skip um at the same level as we did this. We're also going to want a splitter for the path.
The splitter for the path is going to be compared against the other one. So I can compare one element at a time.
Yes, but we're also have going to have to skip the empty ones.
Or I can make this empty thing a configuration.
Hold on. If I just say here bull allow empty and I store this boolean also part of the string splitter and I store it here then the advance um if no eyes.
Oh, well, not really.
I mean, we can here's what I can do. If uh the size is zero and I'm supposed to skip empty, then I'm actually just going to manually advance myself.
This may break very easily, I'm pretty sure.
Uh makes the function a little bit recursive. It could technically break, I guess, but I'm hoping not.
Anyway, back to the router.
Do not allow empty.
In which case, we can get rid of this.
And now we can assume that um if we can't splitter advance the path splitter then we failed. We just break out of this loop and we continue.
Otherwise, we're supposed to be comparing each element against each other like this.
Instead, instead of left hand side, we have the template content uh current and on the other hand, we have the path splitter current. So, we found a match.
Well, we found a partial match.
We'll need to make sure that this match is found for everyone.
So really what we want to do is if the slice match then you found a match otherwise you want to check that the uh template is in fact a template.
And then then the path splitter template split current.
And if this fails and also this fails, then we didn't find anything and we break out of the loop.
I can skip that part for now. I think I hope this runs normally with just prints. Um, line 49. What is that?
Ah, the old code it's not updated to the latest standards.
Not sure why I'm keeping it around. I already copied all of its logic. I I can now delete it.
Okay.
So, this matched this. This matched this.
This matched properly. This matched properly. This did too. This shouldn't have matched.
The the thing is it matched the first time but not a full match. So, I'm not checking for that yet. I'm just checking that, you know, latest is being matched and then this is being matched.
All right.
Um, I just want to use a little Found a true found true.
Well, this can be actually simplified.
and then if found return temp uh test entries I All right. So, we're going to go through each component of these well, we're going to go through each of these options, and then we're going to go through each of the components of these options, which are split by this character, and we're going to check them against each of the components of these paths, making sure that they match at every step of the way. And if they don't, then we failed.
All right. Uh, so parse path actually returns Let's have it do a little print, a little debug print just to tell us that path s matched pattern s where the path is path test entries I All right. So, let's see. So, this matched this. This matched this. This matched on ID. This matched on ID. This matched sort. This matched sort. This matched sort.
Um, we need to check at the end cuz right now we're checking if the path is longer is shorter than the template then we doesn't match the template. But if the template is shorter than the path it also doesn't match but we're not checking against that.
And um frankly just going to be a little lazy.
If we are actually able to advance this this path further then clearly it didn't work and it'll match the next one.
Indeed.
This matches sort. This matches sort.
This matches sort ID. And this matches sort ID.
Okay, that was easy. That was uh simple.
That was uh conveniently simple and easy to do.
All right. Um there's an ad break, so I'll be back in a couple minutes.
Okay.
All right. So, we're doing some pattern matching.
Surprisingly doable, I guess. Surprisingly easy to do.
Now, um pattern matching is all well and good, but we need to store these patterns somewhere. We need to actually do something with them.
Um, essentially right now my file system, if if any of this was actually implemented in a file system and not just a test, um, yeah, my file system is supposed to be able to parse these kinds of paths into the patterns that they match and it seems to do it quite well.
I want I want to test some failures before I continue actually.
For example, um test zero test exists but it's not supposed to be a subdirectory also for sum and what about test and then or zero and then latest.
So I expect these three to fail and it looks like they did because they're not printing anything.
All right. Um, so yeah, parsing of a path is supposed to tell me uh which one of the patterns matched, but it doesn't tell me um what pattern matched.
And uh that's kind of a bummer. That's kind of a problem cuz of course I need to access the information that was parsed in a somewhat easy way. Again, the way that um now I don't think they had an example for this, but the way that Express does it is we got the Where's your examples, my dude? Ah, here it is. Here's an example of how they do it. you do user ID where ID is a parameter and then you just access it by rec params ID because they're using JSON and JSON is particularly great for these things. Now I could use a dictionary probably will need to use a dictionary.
Um, I would love to allow the file system to define its parameters in a sort of very nice neat way and then just uh very nicely just say hey this parameter is a number and then just returns a very nice number and I can just do something like params id and that gives me either a string that I can parse into a number or directly the number that would be cool but I can't I don't think I can I don't think I can I think I am going to have to use a dictionary that gets Um first where each entry just gets put in here.
Well, no uh each parameter matching is going to be put in here.
Yeah, I think that's what I'm going to have to do.
And I'm just going to create a structure to help me with all this. It's going to be a uh path resolution path resolve. Resolution resolution path resolution. All right. um which right now is just going to point me to the path and also to a hashmap params.
We need to include hash data hash map.
You still can play hashmap t hashmat t where we're going to want to return one of these here.
Now, this is where it's going to get a little bit uh weird because we're going to have to allocate the hashmap.
We could limit the capacity. Honestly, I'm going to limit it to 16 for the time being. This should be fine.
I guess I'll also initialize the path to null at the beginning.
And then uh res hat is actually test entries I and you just return that.
Otherwise you have to hashmap destroy.
Do I have that function? Yeah, here it is.
uh the hashmap that was put in here.
Then just change up this condition so that here it matches it returns that otherwise um hashmap empty. There's no hash hashmap empty. So I'll need to create that.
Is there a remove all maybe?
No. So I have to create a hashmap empty um thing that just empties it out. But first is the actually pushing stuff into the hashmap.
which is res params where the key is the template parameter + one.
So, we skip the colon and uh length minus one since we don't have the colon and then the value.
Oh [ __ ] Well, the value we have to allocate.
Uh so we can do strings from slice path splitter current data.
All right. Um so let me create this hashmap empty function.
Pretty sure going to need all this.
Let's see. Uh, if there's no map, no problem. Otherwise, just do a hash. No.
We'll need to empty all of the maps buckets.
I'm going to admit I don't know how to work with uh hashmaps.
What can I say? Um, so the hashmap obviously has buckets and then it has wait hold on maybe the destroy function is iterating through all of them or for each actually is.
Yeah, I'll just copy this code. It's a lot simpler actually.
empty. There we go. Where?
Okay. It's a a limited number of buckets. Capacity is just a number of buckets. So just iterate through that.
Got it.
We're also not freeing the contents of the map when I'm doing this.
That's not really helpful.
We can maybe Uh first free the key, then free the element. Uh and in between you might want to free the value.
All right.
Let's see how that uh works.
There is a case where this is happening.
So also I left a function there that I shouldn't have. This function pointer is no longer needed.
Just keep the one for free.
And Let's do that.
Wait, it's not even a string technically.
You can just call release on it there. Right? That should be freeing the string properly and only returning values if um necessary.
Now I'm also going to create um print args just so I can quickly um test that this is working.
just path matched pattern.
I like that zed does these little things. Helps with formatting a lot.
Hashmap uh for each where we have this function signature.
All right, please work cuz it's been a while and technically all we're doing is string manipulation.
Not exactly routing just yet, but we're getting there. We just need to plug it all together.
And that's amazing.
That's beautiful.
Yeah, I'm going to go with that. didn't work.
Um, this one worked with no arguments. This one worked with no arguments. This one worked with argument zero. Uh, wait.
Yeah. So, I also want you to print the um key.
You can actually print the key as a string slice.
still going to crash. But we can at least check these. Okay, no arguments here. No arguments here. ID zero. ID zero. Sort latest um latest matched pattern. sort sort latest and then it crashes I believe probably when destroying cuz it seems to be crashing when um for the ones that don't actually work.
No, wait. I removed those.
So, never mind.
When are you crashing? Hey, Red Falcon.
What's up?
Um, latest matched pattern sort.
Latest matched pattern sort.
So, it's it's crashing for this one.
Okay. So, you're crashing here on the empty.
Uh so high chance that actually uh empty was already freeing some stuff that I'm now freeing twice because dead beef essentially means use after free or in this case free after free because I'm freeing three things. Uh first off I'm supposed to be freeing the key and length.
Then I'm supposed to be calling the free on the value and then I'm calling Hashmap entry T.
Yeah. Which one of you is uh E next is not actually being freed. So the pointer to it should still be valid.
Not sure what's going on. Yeah, viewership has grown. Uh, file management system in which sense?
Project files or file system for the operating system? Yo, Jester, what's up?
Yo, Jester is busy.
Um, not sure exactly which one of these is is causing the issue.
Uh, if the key length is bigger than this and we're freeing the key the key.
I mean, most likely it's going to be this.
Why do we get stuck on this thing sometimes?
It's not that. Okay. Uh, interesting.
Um, oh yeah, yeah, I'm still working on that.
I'm making a routing system for it so I can define complex system uh file system structures.
Um, oh, you have a value dispose.
Oh, what do you know?
What is this value dispose?
I didn't know that.
Right. So, that actually frees the hashmap empty from having to have this.
And we can kind of just do it like Chester. What are you doing like that?
Okay, I didn't even begin to fix the issue, so this shouldn't change anything, but maybe. I guess we'll see.
I love that whenever you change a header file, it recompiles like half the library for some reason.
Wait, no, he didn't leave code in here, too.
All right, we're going to have to do some prints here.
just X.
I wonder if it's just this and it's just a bug inside the hashmap which so far I haven't freed.
I'm not sure. by red center free valley free in entry and then yeah immediately should all be getting freed I believe and then it goes to the next one.
So why is it getting freed?
Yeah, it's this.
This is using Malik.
Damn, that is old.
Malik is Hasn't been used in a while. Okay. Uh, it's already kind of late and I don't want to keep debugging this. So, we're just going to not free that and just keep testing.
Oh, wait. I'm forgetting one thing in here. Either way, when you empty the maps size is supposed to go to zero.
Wait, I can do something else. Hold on.
Uh, this returns zero if it didn't do anything. Returns one if it did. All right. So, can we make it like return a boolean? For the love of God.
What is this savage C code with zeros and ones?
Let me just hold the size.
I mean, there's a chance that again, the bug doesn't even come from what I wrote.
It comes from this, like from just the hashmap itself. So, there's a chance that I'm going to have to disable this as well. But, um, doesn't matter.
All right. A hashmap remove takes the map.
Oh, it does expect a key and a length, huh?
Why did I think it didn't?
That That was stupid. What the hell?
Oh, why is this const?
It's a empty function. Oh, the other one was a for each, so it wasn't supposed to modify, but this one is.
So, yeah, there we have it.
All right.
Again, u high chance that all of that was for nothing. Well, no, I I already didn't do it, so yeah, should be fine.
I really need to understand why it gets stuck on that command.
Okay. Uh, looks good. But again, there's still a double value here that I don't want. I'm not freeing it properly.
All right. I'm going to do something a little stupid, okay? Cuz I'm having too many bugs to deal with this. And again, I kind of need to move forward. So, I'm just going to do this.
temporary code. All right, I'm just going to destroy the hashmap and start over and hope that destroying the hashmap doesn't actually crash.
Looks fine. And yeah, it works.
I'll I'll have to fix that. actually long overdue for checking a lot of these types and uh getting rid of the Malach calls, replacing them with Zelik and then um doing some more maintenance on them.
So maybe I'll need to start with a hashmap to make sure that this works.
All right. So, I'm going to leave a little to-do here.
Okay.
And we're good. We're now managing to match a uh path to a an entry and getting the parameters from it.
So the last thing we really need to implement is listing the contents of a subdirectory.
Do I really need to have a a special function for that here?
I technically already have something for it. So maybe I just want to implement this in the uh in the stack fs here and then just kind of bring it all together later.
All right. So uh you don't use test entries anymore.
So that is going to have to change.
And actually the path resolution doesn't return char anymore either.
It now returns one of these entries which is a module file.
Is it a module file? Hey, Tony.
Yeah, it's a module file.
And the entries to be parsed. You just take them from here from an array of them.
There we go again with the size.
Uh we're going to need the entries path which we get from the name stack get module actually. No, not like that.
Yeah, like that. Get a module file from entries index i. And then you're going to get the name and that is not the path but the uh pattern.
The pattern.
It's actually just a stack kit.
Okay. And what's your problem? It's a string.
That's not a problem. We're just going to do it like this.
All right. Uh, so now it's going to return a path resolution. And of course, you all will not work anymore.
So instead, I'm going to want to include this stuff in here, router.
And I'm going to test it out by I already had the directory listing, which is also why I'm not super interested in implementing that right now. Instead, I'm implementing u I'm interested in reimplementing um this thing, the stat for my directory.
Where Here we do want to have the path normalization.
Did I keep that function? No, I didn't.
And none of this is in get yet. So, Okay.
Um I want to do parse path given it entries and path and this is going to give me a path resolution then based on this if I don't have a file then return False.
If I I'm thinking should I uh Yeah, I can just do hashmap.
size for the resolution params.
Uh if there aren't any parameters, then I can just fill out the information manually.
which is the type stat and data type which we can actually get from here.
File um data type Otherwise we are supposed to check parameters by doing hashmap remove or get doesn't really matter.
with key sort length of four.
Kind of want to create a um helper for this also.
static inline hashmap get string const hashmap t map conch char string which just returns map string uh maybe using the word string is not the best str len str and I forgot to give it a return type which is void pointer.
All right, back to this.
Um, if latest has a value, then we're supposed to invert the entry that we're spec requiring.
If not then we're not supposed to do that.
Uh but here we do need to do an id by doing hashmap get string also I forgot to do the string here resolution params and the string be ID if there is no ID we return falsemap hashmap There we go.
And then well this is ID string maybe cuz this is ID by parsing the ID string with its size.
and if latest then id equals to stack count uh what's the name of the count uh data minus ID so we invert it also if the ID is bigger or equal to the stack count.
Now we probably failed somewhere. So we return false.
And finally we get our buffer.
from which we're going to get the information for the file but we get it from ID.
Now the data type which is this kind of voluntary tagging type system for the file system. Um we kind of lose that right now but honestly this buffer type should have it because buffers are meant to be helpers to work with files or with any kind of data like that. and the file system is supposed to be able to handle that type of stuff with um types. So, stands to reason that the buffer should have a type. I'll add it in a second. Want to see if this works, though.
What the [ __ ] are you complaining about now? Genuinely, what are you complaining about? Yeah, I'm pretty sure it's complaining because I had to include the string.h in the hashmap.
So, I could bring in strl len.
Uh, which by the way didn't even point me to the correct place. Doesn't matter.
What an ugly syntax. Jesus Christ.
A lib never fails to disappoint.
Okay, what are we complaining about now?
Text draw string delete previous declaration instead of buddy. What?
What do you mean previous declaration inside of hashmap?
This is an extern. It's not a declaration.
All cuz I made this damn helper. Hold on. Christ.
All right. Lesson learned.
Just move the helper over here.
Why are you still complaining about stringh?
Oh, the extern declaration is still here. Again, the way that extern declarations are supposed to work is that they just you're just kind of say, "Hey, this function exists somewhere, but you're not defining it." So, why I'm getting a double um double function declaration error? I have no idea. But whatever.
Probably C++ compiler complaining somewhere. I don't even want to know. Anyway, now that we have this routing implemented properly, we now just have a panic for no reason.
What else are you complaining about? Oh my god, how is it an undefined symbol?
How did my function go from being declared twice to never being declared?
How did this h how did this happen?
Why am I having trouble with strlen?
This is ridiculous. It's a function that I've implemented in in a million different places.
All right.
What are you complaining about?
Undefined reference to strlen in hashmap. C which is in string.h.
Is it Is this the wrong path? Maybe.
Yep.
Whatever, man.
Anyway, yeah, failed to get info for clipboard.
Um, so there is uh something here didn't work.
It didn't parse.
Oh yeah, I forgot to actually have this one as a stat out stat return true.
Looking up at the m mostly is this on Android.
Can you even do it on iOS and Apple TV?
Probably not.
Okay. Okay. It seems to be uh finding them. It didn't find it for latest, funnily enough. Latest didn't match.
This didn't match. This, this, and this did.
Oh. Uh, the reason it didn't match is because I forgot a return here, which I'm filling out the data. And then one of these fails which returns false. This is actually returned true.
Those two don't have param. No. Latest has a parameter.
I don't know. Let me see. All right.
This is back at least. And it actually has the right information. Um although that's still pretty hardcoded.
Latest. I don't know what's happening with you.
Zero failed to open file. That makes sense. I haven't implemented actually opening um latest. I'm a little surprised to see that clear path latest matched pattern sort with sort. Oh, because there's no ID.
Yeah. Um, stop.
Darn. Trick.
All right, let's see.
Okay, now this opens. This crashes.
Um then again that's not using the latest and greatest ironically enough but it doesn't recognize it as a directory. It uh recognizes these as files and again it cannot open them because the actual thing to open them happens here.
Now um essentially what I was trying to do I already did. What I need to do now is the same thing that I just this function pretty much that I just implemented I need to implement in um reading a directory.
I'm pretty sure that's the only place.
And then I need to do the same logic that I did in order to do this but for listing the contents of a directory.
Again, very similar kind of um kind of logic.
Um so really just copying and pasting code won't be particularly interesting. But before I end the stream though, I did say this is somewhat important.
that the buffer should have a data type, a data signature.
Where do I implement this data signature sh in data signature.h. It was literally right under the file that I'm working on.
And the buffer itself won't do anything with this information. But when we write, we create a new buffer.
We give it the data type from the file descriptor I believe. Yep.
And uh when we're doing stat, the data type, get rid of that to-do.
The data type comes from the buffer data type. Maybe now it'll show text data type if everything is working correctly.
It isn't. Um C++, I hate you. You're so stupid. I don't know what else to call you. You're just stupid.
It's complaining because this initializer doesn't initialize all the values explicitly. Oh my god, this is such a problem. Oh my god, I'm C++. I'm really stupid.
Just add two lines of code that do absolutely nothing.
Come on, man. [ __ ] off.
All right. and it marks them as text.
Uh, this one should have also done it.
It does not.
I guess it's also up to me to kind of hardcode that logic into my current this thing.
It's not a warning. It's an error.
Probably should disable it, I guess. But I would much rather disable the entire language if I'm completely honest with you.
Um, stack fs stat file or stat data with a i64 ID, right? You just go and dfs that [ __ ] like that.
All right. So, I'm just going to create this function to do this for me.
return true unless the buffer is null, which by the way I'm not checking for.
Feel like that's not the first time that your little brother turns off the internet.
Return stack fs stat data with the ID that we've been given and the outstat that we've been given.
All right. So, this file gets the latest information.
And again, because this one has hard-coded um information for getting data from the file works pretty well.
Now what happens when that file is not uh does not have um yeah when there's nothing in the clipboard this file is just shown as empty nothing inside of it. Cool.
Feel I feel like blocking MAC addresses does not protect you from uh physical attacks.
Okay. And I'm going to keep these logs just in case I need them.
I also turn that off.
And yeah. Okay. Final thing is this match param thing.
Uh, can I do a forward declaration of it where I just say it exists here maybe as x turn and then I actually declare it here follows non-static declaration.
Can I do static extern? No.
Can I do this? Okay, this works. I can do a forward declaration with static. I didn't know that.
Which means I do a forward declaration here. I use it in this header file. Then the entire thing gets imported. Bada boom, bada boom. The function is actually declared here.
which of course makes sense because that function is what declares what an ID and what sort are.
So we're good. Now this is a fully configurable router. The only thing that it doesn't do is list which again I might not even need to do that. I might just be able to implement it directly in here. I don't think there's any special logic.
All right. So, uh, everything from now on is just boiler plates. Just writing the same code that I wrote here in a bunch of other places for reading and writing files that don't really exist.
Um, all of these were actually already um virtual files, but now they're virtual virtual files because before they were virtual files in the sense that they don't exist on any drive, but they are declared in the file system with this module file thing that I've referred to in a few places. They have one of these, but now they're virtual virtual files because they don't even have one of these. This matches a template. And then using the arguments, I get the actual contents, which is a buffer, not a file.
Oh, well, you don't need any keywords for function declarations.
No, that's true. just um I'm using static just because like you can import this in multiple places and then you can have multiple declarations like that can be a problem cuz like this VFS for example I'm using this header in multiple places and each of them has their own implementation. So that's kind of what I mean.
All right. Well, uh, that's going to be the end since everything from now on is just going to be boiler plate that I honestly don't feel like writing at almost midnight on a Monday.
So, I'm going to end the stream here.
I'm going to not do file system stuff until Friday.
I don't know what I'm going to work on on Friday because that's the end of an era.
I I think I'm going to enjoy the benefits of all the hard work that I've put into the file system and I'm going to be able to expand it quite a lot.
Uh since even though I have somewhat expanded it quite a lot um since all of the blue things here and even this and this and this um are fully defined file system modules. They're much more simplified than I want them to be. Like I said, actually the language right now only supports one project and no programming languages, but still if it did, it would only support one.
Uh now I can make more complicated stuff now that I have parameters.
But again, going to enjoy the benefits of that on Friday, maybe, unless I come up with something better to do, I guess.
But anyway, thank you so much for watching, everybody. I'm going to stream again on Friday. I I don't think I'm going to stream in between. So, yeah, Friday at uh 8:30 Central European time and 7:30 UK time.
There's an ad starting in 1 minute, so I'm going to end the stream quickly.
Thank you so much for watching. and I'll see you then.
Ähnliche Videos
resume fixed instantly 😭 Comment “app”andI’ll sendyou the link #parakeetaipartnership #resumetips
Ritcareer
686 views•2026-05-31
Re: 🗣️📍theprophedu📍2026 GST 103 CLASS (E-EXAM REVISION)
theprophedu
636 views•2026-06-04
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
Making Minecraft Clone with C++ & Raylib
PecaCSLive
686 views•2026-06-04
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Instagram accounts got PWNed
EricParker
13K views•2026-06-03











