FBB::Mstream(3bobcat)
π FBB::Mstream β Message handler π
okay so bestie, pull up a chair, because we're talking about FBB::Mstream(3bobcat) β the generic message handling stream. it's giving organized, it's giving labeled, and ngl it's about to make your error messages look so much better than a raw std::cerr << "oops". π
β¨ NAME β¨
FBB::Mstream β Generic message handling stream π¦
β¨ SYNOPSIS β¨
#include <bobcat/mstream>
Linking option: -lbobcat
β¨ DESCRIPTION β¨
so, objects of this class handle your messages in a standardized way. like, unbothered, consistent, iconic. Messages may be prefixed with order (line) numbers and/or labels, so your output actually tells you what happened and when. And as a lil extra flair, messages generated by Mstream objects may optionally end by throwing an FBB::Exception (which is an std::exception, so it plays nicely with the rest of the world) β which makes implementing stuff like fatal error messages genuinely simple. no cap. π₯
The BOBCAT library provides four message streams, and you can use them as soon as you've included the mstream header file. They're all defined in the FBB namespace:
FBB::emsgβ for generating standard (labeled and numbered) error messages, e.g.
[Error 1] this is an error message
FBB::fmsgβ for generating (labeled) fatal error messages, ending in an exception, e.g.
[Fatal] this fatal message is followed by an exception
The exception's what member contains FBB::fmsg's id value (see the member id below).
FBB::imsgβ for generating plain informational messages, e.g.
this is a plain message
FBB::wmsgβ for generating (labeled) warning messages, e.g.
[Warning] this is a warning
By default all messages are inserted into the standard output stream, but other destinations (standard error, a named file, etc.) can easily be configured. so you're not stuck, bestie. π
Mstream objects themselves are std::ostream objects, which means they can totally be passed to functions expecting ostream arguments. main character energy fr fr. π
Messages inserted into Mstream objects are buffered until the buffer is flushed by their std::ostream parts, or when either the FBB::endl or FBB::flush manipulator is inserted into the message stream. And here's the cute part: since these manipulators act like std::endl and std::flush when inserted into another kind of std::ostream object, using FBB::endl and using FBB::flush might be worth considering. also β when using namespace std and using namespace FBB are specified, the FBB::endl and FBB::flush manipulator will automatically be used with Mstream objects. so convenient, we're obsessed. ππ
Messages inserted into Mstream objects are considered completed at the insertion of the FBB::endl or FBB::flush manipulators. Message labels, line number labels and line numbers will only be shown for the next line after these manipulators have been inserted, and exceptions are, if needed, thrown from these manipulators. so yeah β the manipulators are doing a lot of heavy lifting here. respect. π«Ά
β¨ NAMESPACE β¨
FBB
All elements mentioned in this man-page, are defined in the namespace FBB. πΈ
β¨ INHERITS FROM β¨
std::ostream
β¨ CONSTRUCTORS β¨
Mstream()β the default constructor generates messages using thestd::streambufused bystd::cout. There is no limit to the number of messages that may be inserted. No message or line numbers are shown, and no exceptions are thrown when inserting messages. chill vibes only. πexplicit Mstream(std::ostream &ostr, size_t maxCount = std::numeric_limits<size_t>::max(), std::string const &tag = "", bool throwing = false)β this constructor uses thestd::streambufthat is also used by theostreamostr. By default (i.e. using the default argument values) there is no limit to the number of messages that may be inserted, no message or line numbers are shown, and no exceptions are thrown when inserting messages. β¨ Specifying any other value thanstd::numeric_limits<size_t>::max()will set the maximum number of messages that can be inserted to that value. The tag defines the text of the message label (e.g.,Error).
When throwing is true an exception is thrown after completing a message. The generated exception's what member may show the FBB::Mstream object's id (see below at the member id) of the Mstream object throwing the exception.
explicit Mstream(std::streambuf *buf, size_t maxCount = std::numeric_limits<size_t>::max(), std::string const &tag = "", bool throwing = false)β this constructor uses buf to insert messages into. The remaining parameters are identical to those of the previous constructor. same energy, different destination. π«explicit Mstream(std::string const &name, size_t maxCount = std::numeric_limits<size_t>::max(), std::string const &tag = "", bool throwing = false)β this constructor creates astd::ofstreamfrom the provided name parameter. It throws an exception if the stream cannot be opened for writing. If a file by that name already exists it is rewritten β so heads up on that one, bestie. β οΈ The remaining parameters are identical to those of the previous two constructors.
lowkey important: copy and move constructors (and assignment operators) are not available. no duplicating this stream, periodt. π
π MEMBER FUNCTIONS π
okay bestie, here's the whole toolbox, every single one, no skips π₯
size_t count() constβ hands you back the number of messages that got inserted. and if you calledsetCountat some point, it's the value from that lastsetCountcall plus however many messages have been inserted since then. math but make it messages πbool isActive() constβtrueif messages can actually make it into theFBB::MStreamobject,falseif inserted messages are just getting ignored. heads up: while it's ignoring stuff, the message count does not get updated. ghosted messages don't count fr fr.int id() constβ the unique id of theMstreamobject. it's giving government name πͺͺbool lineExcess() constβtrueonce you've tried to insert one more message aftermaxCountmessages already went in. you overstayed, bestie πstd::string const &lineTag() constβ the line-tag currently in use. default isLine. β¨size_t maxCount() constβ the maximum number of messages that can be inserted. if what comes back equalsstd::numeric_limits<size_t>::max(), then congrats, there's literally no limit, the limit is a myth πvoid noLineNr()β calling this suppresses the display of a line number, but only if you call it aftersetLineNr(scroll down π) and before a message is being inserted (or has already been inserted). timing is everything πvoid off()β after this, any message you insert into theMstreamobject gets silently ignored. and nope, the internal message counter does not get incremented when messages are inserted. silence, but make it on purpose π€«void on()β this is the default state, and after calling it, messages inserted into theMstreamobject get sent to their destination stream. we're back, baby πvoid reset(std::ostream &ostr)β messages inserted into theMstreamobject now get handled by thestd::streambufthatostralso uses. everything else (likemaxCount, the message label) stays exactly as it was. only the vibe of where changed.void reset(std::streambuf *buf)β messages inserted into theMstreamobject now get handled by thestd::streambufbuf. other parameters (e.g.,maxCount, the message label) are kept as-is. same energy, different buffer.void reset(FBB::Mstream const &mstream)β the current object gets reset using the parameters of themstreamparameter. copy-paste but for settings πvoid reset(std::string const &name)β messages inserted intoMstreamobjects get handled by astd::ofstreamcreated using thenameyou passed. if the stream can't be opened for writing, an exception is thrown. and yes, if a file by that name already exists, it gets rewritten (so, gone, bestie π). other parameters (e.g.,maxCount, the message label) are kept as-is.void reset(std::ostream &ostr, size_t maxCount, std::string const &tag, bool throwing)β messages inserted intoMstreamobjects get handled by thestd::streambufthatostralso uses. if you specifystd::numeric_limits<size_t>::max()formaxCount, there is no limit to the number of messages that thisstd::streambufmay handle.tagdefines the text of the message label (e.g.,Error, or the empty string for no message label at all). whenthrowingis specified astrue, an exception is thrown after completing a message. dramatic much? correct answer: yes β¨void reset(std::streambuf *buf, size_t maxCount, std::string const &tag, bool throwing)β messages inserted intoMstreamobjects get handled bystd::streambufbuf. the remaining parameters are identical to those of the previousresetmember. same deal, new home π¦void reset(std::string const &name, size_t maxCount, std::string const &tag, bool throwing)β messages inserted intoMstreamobjects get handled by astd::ofstreamcreated using thenameyou passed. it throws an exception if the stream can't be opened for writing. if a file by that name already exists it is rewritten (rip to whatever was in there π). the remaining parameters are identical to those of the previous tworesetmembers.void reset(FBB::Mstream const &mstream)β the current object is reset using the parameters of themstreamparameter. and here's the glow-up: following the reset, all of the current object's parameters can be modified independently from those used bymstream. it's giving main character energy, you're your own person now πbool setActive(bool ifTrue)β ififTrueequalstruetheMstreamgets activated, otherwise its actions are suppressed. and it returnsifTrue. polite and functional π«Άvoid setCount(size_t count)β assigns the valuecountto the object's message counter. reset the tally, bestie π’void setLineNr(size_t lineNr)β sets the valuelineNras the message's line number for when the next line is displayed (peepnoLineNrtoo π). lowkey important: this value is not changed by theMstreamobject itself. to display another line number you'll have to call this member again β meaning the line number does not just automatically show up again at every new line. you have to keep asking. needy, but iconic.void setLineTag(std::string const &tag)β sets the tag that prefixes line numbers. by default the line tag equalsLine. πvoid setMaxCount(size_t maxCount)β definesmaxCountas the maximum number of messages that can be inserted into theMstreamobject. the ceiling. the cap. the limit πΈvoid setTag(std::string const &tag)β specifies the tag that prefixes messages. by default the tag is empty. if it's not empty, the tag is enclosed by square brackets. e.g., specifying the tagErrorwill prefix messages with[Error]. so cute, so labeled πstd::string const &tag() constβ returns the message tag currently in use. by default that's an empty string. nothing there. a void. a moment of silence π€«bool throws()β returnstruewhen theMstreamobject will throw an exception at the next completed message. the generated exception'swhatmember contains the id (see earlier for the memberid) of theMstreamobject throwing the exception. snitch behavior, honestly πvoid throwing(bool ifTrue)β modifies the behavior ofMstreamobjects at completed messages. after passingtrue,Mstreamobjects will throw an exception at the next completed message, otherwise this exception is not thrown. the generated exception'swhatmember contains the id (see earlier for the memberid) of theMstreamobject throwing the exception. same id-in-the-error situation as above bestie π₯
π§ MANIPULATORS π§
quick note before we dive in: the following two manipulators are not members of the class Mstream. they're free functions defined in the namespace FBB. plot twist π¦
std::ostream &endl(std::ostream &out)β this manipulator inserts a newline character into theMstream's stream and then callsFBB::flush. and when you insert it into some other kind ofstd::ostreamobject, it acts just likestd::endlandstd::flush. dual citizenship β¨std::ostream &flush(std::ostream &out)β this manipulator completes the message that's currently being inserted into anMstreamobject. it flushes the object's destination stream and gets the object ready for the next message. when the object'sthrowsmember returnstrue, it throws an exception whosewhatmember contains the id (see earlier for the memberid) of theMstreamobject throwing the exception. when used with another kind ofstd::ostreamobject, it acts likestd::flush. versatile queen πstd::ostream &noid(std::ostream &out)β this manipulator completes the message currently being inserted into anMstreamobject. it flushes the object's destination stream and prepares the object for the next message. when the object'sthrowsmember returnstrue, it throws an exception whosewhatmember does not contain theMstreamobject's ID. (see how it'snoid? no id. the name ate π ) when used with another kind ofstd::ostreamobject, it acts likestd::flush.std::ostream &noidl(std::ostream &out)β this manipulator inserts a newline character into theMstream's stream and then callsFBB::noid. this manipulator acts likestd::endlandstd::flushwhen inserted into another kind ofstd::ostreamobject. it'snoidbut with a line break, hence thel. iykyk π
since the manipulators FBB::endl and FBB::flush act like, respectively, std::endl and std::flush when inserted into another kind of std::ostream object, maybe consider the declarations using FBB::endl and using FBB::flush. worth thinking about, bestie π«Ά also, when using namespace std and using namespace FBB is specified, the FBB::endl and FBB::flush manipulators will automatically be called when inserting endl or flush into Mstream objects. auto-pilot, slay β
πΈ EXAMPLE πΈ
#include <iostream>
#include <algorithm>
#include <iterator>
#include <bobcat/mstream>
using namespace std;
using namespace FBB;
int main(int argc, char **argv)
try
{
cout << sizeof(Mstream) << β β << sizeof(Mbuf) << β\nβ;
imsg << "Informational: " << endl;
imsg.off();
cout << "The i-msg stream is now off. This message should appear once" <<
endl;
imsg << "The i-msg stream is now off. This message should appear once" <<
endl;
imsg << "The i-msg stream is now off. This message should appear once" <<
endl;
cout << "But this message is shown" << endl;
wmsg << "Warning message" << endl;
emsg << "Oops, this this is an error (not really)" << endl;
emsg << "Oops, this goes wrong, too" << noid;
imsg.on();
imsg << "And another informational msg: " << emsg.count() <<
" error messages\n" << flush;
emsg << "Third error" << endl;
emsg.setMaxCount(3);
imsg << "Msg in between" << endl;
imsg.setTag("tag");
imsg << "tagged message" << endl;
imsg.setTag("label");
imsg << "labeled message" << endl;
cerr << "(cerr) LineExcess: " << emsg.lineExcess() << ", count = " <<
emsg.count() << endl;
emsg << "Fourth error\n" << noid; // no id is shown
emsg << "Fourth error\n" << flush; // shows id (remove the previous
// statement)
cerr << "(cerr) LineExcess: " << emsg.lineExcess() << ", count = " <<
emsg.count() << endl;
cerr << "Beyond\n";
}
catch(exception const &e)
{
std::cerr << "Got a std::exception: " << e.what() << β\nβ;
}
catch(...)
{
std::cerr << "Got an exception\n";
}
π FILES π
bobcat/mstreamβ defines the class interface
π¦ SEE ALSO π¦
bobcat(7), exception(3bobcat), mbuf(3bobcat)
π BUGS π
None Reported. flawless behavior, no notes, periodt π
π¦ BOBCAT PROJECT FILES π¦
okay bestie, here's where to actually find everything, the receipts, the links, the whole fit π
- https://fbb-git.gitlab.io/bobcat/ β the gitlab project page, that's the main character right there π
Debian Bobcat project files, aka the packages you install, no cap:
libbobcat6β the debian package holding the shared library, the changelog and the copyright note πlibbobcat-devβ the debian package holding the static library, the headers, the manual pages, and the developer info β¨
π BOBCAT π
okay so, plot twist, the name is an acronym fr fr β Bobcat stands for Brokkenβs Own Base Classes And Templates. iconic name behavior honestly π
π«Ά COPYRIGHT π«Ά
This is free software, distributed under the terms of the GNU General Public License (GPL). free software is the moment, we love to see it π
π AUTHOR π
Frank B. Brokken (f.b.brokken@rug.nl). not me being obsessed with the person who literally wrote all of this ππ
that's the whole page bestie, you made it to the end πΈ this whole thing is libbobcat-dev_6.15.01, dated 2005-2026, and the page itself is FBB::Mstream(3bobcat) β go read the source, go write something cute, and remember: read the docs, slay the bugs β¨π
π¦
π¦ where this page comes from
- ubuntu stonking: libbobcat-dev 6.15.01-1 Β· GPL-3.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms