Page 1 of 1
Implementing C++ Output Streams
Posted: Tue Nov 03, 2009 10:37 pm
by blah569
[I have split this topic from here as it's quite a change of subject! - AJ]
Firestryke31 wrote:A preliminary screenshot of the latest iteration of my OS, "Socks."
SocksPrelim.png
I've got physical/virtual memory management, a simple initial display driver, and have just implemented ISR support. Next I have to implement the system call interface so I can get the IPC system running so I can get the driver interface set up.
The initial display driver, simple kernel heap, and physical memory manager are all C++ classes. The display driver even uses << for text and integers.
Looks really nice, and pretty convenient to be able to use "<<"
Re: What does your OS look like? (Screen Shots..)
Posted: Tue Nov 03, 2009 11:03 pm
by Firestryke31
Yeah, when I first set it up I was amazed at how easy it was to do. Just overload the global functions class& operator<<(class& in, const char* str) for strings and class& operator<<(class& in, const unsigned int) for integers. In my setup these then call class functions to do the actual display, but some just have them as "friend" and make them do the real work. Finally, just return in and you're done.
Re: What does your OS look like? (Screen Shots..)
Posted: Wed Nov 04, 2009 4:08 am
by Creature
Firestryke31 wrote:Yeah, when I first set it up I was amazed at how easy it was to do. Just overload the global functions class& operator<<(class& in, const char* str) for strings and class& operator<<(class& in, const unsigned int) for integers. In my setup these then call class functions to do the actual display, but some just have them as "friend" and make them do the real work. Finally, just return in and you're done.
Same here, the only thing I ran into was the ambiguity for chars and integers. I ended up using a small 'hack' that prints a character when you use character formatting (e.g. 'c') and always prints an integer when you enter a number (even if that number could be a character). If you absolutely want a number to be printed as char, you'd have to enter either unsigned char(number) or char(number) or something.
Re: What does your OS look like? (Screen Shots..)
Posted: Wed Nov 04, 2009 5:12 am
by AJ
Hi,
Creature wrote:Same here, the only thing I ran into was the ambiguity for chars and integers. I ended up using a small 'hack' that prints a character when you use character formatting (e.g. 'c') and always prints an integer when you enter a number (even if that number could be a character).
Another way to deal with this is by inserting an enumeration in to the stream. For example:
Code: Select all
myOutputClass << myOutputClass::Hex << 'a'; // displays '0x61'
myOutputClass << myOutputClass::Decimal << 'a'; // displays '97'
myOutputClass << myOutputClass::Character << 'a'; // displays 'a'.
So the enumeration acts as a type modifier for formatting the output. If you do this, I would suggest that you create the output class with a default output type - for example hexadecimal. This way, once the class receives the character, it automatically reverts to hex and so you don't have to explicitly send the state enumeration prior to every character write.
Cheers,
Adam
Re: Implementing C++ Output Streams
Posted: Wed Nov 04, 2009 6:36 am
by pcmattman
This way, once the class receives the character, it automatically reverts to hex and so you don't have to explicitly send the state enumeration prior to every character write.
Alternatively, have the class keep track of the last state enumeration used:
Code: Select all
outputClass << outputClass::Hex << 0xdeadbeef; // "0xdeadbeef"
outputClass << 0xf00d; // also "0xf00d"
outputClass << outputClass::Dec << 1234; // "1234"
Re: Implementing C++ Output Streams
Posted: Wed Nov 04, 2009 6:49 am
by AJ
Hello,
pcmattman wrote:Alternatively, have the class keep track of the last state enumeration used:
Equally valid, but my reason for avoiding this would be:
Code: Select all
outputClass << outputClass::Hex << 0xdeadbeef; // "0xdeadbeef"
myIntialisationFunction(); // may or may not use outputClass (I know - global objects == bad :o) )
if(something)
{
outputClass << 0x1234;
}
else
{
outputClass << outputClass::Dec << 5678;
}
outputClass << 0xf00d; // also "0xf00d" - or is it?
outputClass << outputClass::Dec << 1234; // "1234"
I would rather have the class reverting to a known state, because otherwise you could very easily have the situation where each call to the output steam uses the enumeration "just in case" it hasn't been left in the appropriate state.
Just personal opinion
Adam
Re: Implementing C++ Output Streams
Posted: Wed Nov 04, 2009 7:13 am
by Solar
You can't really define this any different than the ios_base modifiers from the C++ standard library do, because otherwise you would have two ways to do output that look identical but aren't really (Bad Thing (tm)).
And ios_base modifiers are "sticky", i.e. they remain valid until overruled by some other modifier.
Re: Implementing C++ Output Streams
Posted: Wed Nov 04, 2009 9:37 am
by Firestryke31
The entire purpose of my class was to have some basic way of getting info to the screen so I could debug until I got the proper CRT and display drivers running, which won't be for a while. I didn't care about being just like the C++ STL's cout. YMMV.
Re: What does your OS look like? (Screen Shots..)
Posted: Wed Nov 04, 2009 12:11 pm
by Creature
AJ wrote:Hi,
Creature wrote:Same here, the only thing I ran into was the ambiguity for chars and integers. I ended up using a small 'hack' that prints a character when you use character formatting (e.g. 'c') and always prints an integer when you enter a number (even if that number could be a character).
Another way to deal with this is by inserting an enumeration in to the stream. For example:
Code: Select all
myOutputClass << myOutputClass::Hex << 'a'; // displays '0x61'
myOutputClass << myOutputClass::Decimal << 'a'; // displays '97'
myOutputClass << myOutputClass::Character << 'a'; // displays 'a'.
So the enumeration acts as a type modifier for formatting the output. If you do this, I would suggest that you create the output class with a default output type - for example hexadecimal. This way, once the class receives the character, it automatically reverts to hex and so you don't have to explicitly send the state enumeration prior to every character write.
Cheers,
Adam
I'm also using the enumeration approach for std::hex, std::bin, std::oct, etc. (they are just custom values in an enumeration that act similar to the standard library). For characters, I've thought of this approach as well, but I found it to be rather inconvenient to have to type that every time, so I just stuck with the 'g' and char(200) approach.
Re: Implementing C++ Output Streams
Posted: Fri Nov 06, 2009 8:37 am
by AJ
Hi,
Solar wrote:You can't really define this any different than the ios_base modifiers from the C++ standard library do, because otherwise you would have two ways to do output that look identical but aren't really (Bad Thing (tm)).
One of the rare times I disagree with Solar
IMO, if you're keeping this internal and do not use the same naming system as the Standard Library, then it's OK to do it differently [ducksandruns]. On the other hand, if you plan doing this in the std:: namespace and then decide to include your new system in your user library, that's different
Cheers,
Adam
Re: Implementing C++ Output Streams
Posted: Fri Nov 06, 2009 10:36 am
by Owen
The thing is you end up with two interfaces which are 99% the same and 1% different.
Too confusing, IMO.
(Though I've never liked C++ input streams anyway; output streams are OK, but printf is better)
Re: Implementing C++ Output Streams
Posted: Fri Nov 06, 2009 1:12 pm
by AJ
Hi,
For the sake of not coming back to a religious war when I next come online, I'll admit "It may not be the
best idea from a
standards point of view, but it works well in practice I do it anyway."
In my defense, I should point out that where I
do name stuff in the same way as a standard dictates (malloc, free, printf...), I'm anally retentive about ensuring it does follow the standard to the letter.
Cheers,
Adam