Older blog entries for elanthis (starting at number 371)

Going Organic

I’ve never been much of a health nut, but there are a few things I’ve tried to pay attention to. I avoid drinking soda as much as possible, especially anything with corn syrup in it. I buy organic meat (no steroids), and preferably buy the stuff raised the old-fashioned way and not on a large industrialized farm. I drink soymilk instead of regular milk, especially since the doctor recommended that one to me. I eat organic oatmeal. Other than the occasional splurging on fresh organic fruit or a trip to Zingerman’s, that’s about the extend of my organic buying.

A friend who is very big into the organic food and local farming lifestyle has kind of given me a bit more motivation to try harder. After my last shopping spree, I’ve managed to convert about 1/3 of my diet to all organic products without really raising my grocery bill much. I still have a ways to go.

The biggest problem I’m noticing is a lack of pre-made or semi-made foods that are all organic. For example, I can get the ingredients to make some kick-ass pasta sauce (along with all organic wheat pasta) easily enough, but finding a bottle of already made sauce is another thing altogether. I’m lazy. I don’t really know how to cook, and even if I did, I don’t think it would be something I’d do more than once or twice a week. Especially not in this stupid apartment with the neglectful landlord who won’t get rid of the ant problem that makes my kitchen close to unusable.

So, most of the organic food I’ve bought is stuff I can eat with little to no cooking or preparation. That mostly comes down to snacks and light meals, but not the kind of stuff I can really live off. I’d love to see a bigger variety in organic cheeses (the only ones I can find are generally whole wheels that cost a fortune), pre-made sauces and side-dishes, and so on. I’d also like to see a bigger variety in organic and whole-wheat pasta; I can’t find farfelle organic pasta for the life of me, for example.

Assuming I could find such products, I could get my diet up to at least 3/4 organic foods, with the rest of my diet being from restaurants (and several of my favorite restaurants are all organic).

My last major sin in terms of food consumption would then be that I drink bottled water. A lot of bottled water. About 150% to 200% of what the average person goes through. I don’t know why, but my body needs more water than most people. I sweat heavily even in cold weather. My father is the same way. Also, I just can’t freaking stand tap water. I mean, to the point that drinking it actually makes me gag a little. It might be that I was raised on nasty well water and I’ve been conditioned to hate tap water, but I swear even the filtered city water I have now is pretty gross. Now, I don’t believe that bottled water is bad for me (it isn’t), or even that drinking that water is bad for the environment (it isn’t), but the huge number of plastic bottles I go through is enormous. We don’t have recycling collection around here, and even if we did, it’s generally shown that recycling creates more waste due to the energy recycling and collection requires than just throwing the stuff out. I’ve tried a few alternatives to drinking bottled water, including the reusable water jugs that stores like Meijer has, but that water tastes almost as bad as tap water (that’s probably all it is). I wonder what other alternatives are available given that I just will not drink tap water?

My cupboards currently contain a few foods I bought earlier this month that, once consumed, I’ll replace with organics. I’ve got a jar of peanut butter (which, honestly, I need to cut out of my diet - that stuff is going to be the death of me), some farfelle, Kraft Macaroni and Cheese, and some jars of Kroger brand strawberry preserves. Everything else is organic, a lot of stuff is whole-wheat (I haven’t eaten white bread in more years than I can count, except for the occasional baguette), and a few things are possibly even locally grown (most of it isn’t, though).

I’ve also started taking some “all natural” vitamin supplements, as it’s been pointed out to me that my general diet sucks and I’m probably missing all sorts of crap my body needs, which combined with my lack of working out for the last year and half has led to some severely deteriorated health. I’m sick for the second time in less than a month, for example.

Laura also gave me some recipes for some very easy to prepare dishes I might try out once the fucking ant problem is solved. (This might have to result in me threatening legal action for landlord negligence due to failure to correct unsanitary living conditions. Fun.)

Syndicated 2008-01-31 05:17:37 from Sean Middleditch

Back to Fedora

I’ve been using Ubuntu pretty much since it first came out, after Jeff Waugh sent me an invite. (I forget why he did so - possibly I was bitching about whichever distro I was on at the time.)

Ubuntu was pretty great until the last few releases. Starting around the time of Feisty, the number of bugs seemed to be creeping up and up, and more effort was being put into adding horrifically fucking stupid features like “Compiz by default” (whoo, an ugly and eye-straining WM that only works on less than half the hardware out there with OSS drivers, just what we needed).

Some of the bugs were really starting to impact the usability of the desktop for me. They weren’t getting fixed, but new stupid-ass features were being added all the time. I gave up.

Having heard good things about the last few Fedora releases, I decided to reinstall my desktop with Fedora Core 8. The install went very smoothly (unlike Ubuntu, with its idiotic Live CD installer that takes longer to boot than it does to install, and usually crashes or locks during said install), and I’ve got the system up and running.

The first problem I ran into was not being able to log in as my user. I had left the /home partition unformatted. I had also left the default SELinux settings in Fedora enabled. The problem was that the /home partition was not labeled, and so my user could not access his own home partition. After a few minutes of learning the SELinux commands, I fixed that up.

Next, the display in the desktop was practically unusable. The max resolution supported was 800×600, and I had no mouse cursor. I had to reconfigure the monitor to a generic LCD 1680×1050 to fix the resolution, but I still had no mouse cursor, and everything was looking stretched even though the right resolution was being used.

The nv driver had been selected by default, so I switched to the nouveau driver, which I’ve been wanting to try for a while now. Switching the driver gave me a mouse cursor, but things were not peachy. The color of my desktop kept randomly changing, and the screen was somehow taller than the monitor, so even after auto-adjusting the top of my screen was not visible. Plus, just like with the nv driver, all my fonts looked like shit, and were stretched out too wide. It’s like neither of the drivers support wide-screen monitors correctly, even though they were running in the right resolution (well, maybe nouveau wasn’t, even though it was told to).

So, I installed the nvidia binary driver from the livna respository, and blam, everything looks great now. This a real shame that just getting basic 2D functionality working still requires the binary driver. ::sigh::

I’ve since tweaked a few other things, and am still doing getting everything up and running just right. The only other actual problem I’ve had so far is that all the channels on my soundcard were set to 0 and muted. Weirdness.

All of the bugs I had in Ubuntu are gone, though. Including bugs which I would have guessed were GTK+ or X bugs. So either Fedora is actually bothering to fix stuff, Ubuntu’s new feature squad is breaking stuff, or the bugs only manifest with a certain combination of software versions that is different on Fedora. All the base package versions are the same, though.

Oh well, I can use my computer now without constantly getting frustrated by stupid bugs. Yay me!

Syndicated 2008-01-26 21:32:35 from Sean Middleditch

Bike Show Photos

More photos of the 20th Annual Custom Bike Show in Birch Run, MI.

Facebook album

Dad’s public Picasa gallery

The show was sponsored by Bubba’s Tri-City Cycles, and the four beautiful models we took way too many pictures of are employees of M/C Leather Works.

Syndicated 2008-01-23 23:52:12 from Sean Middleditch

Bike Show - First Place in Class

We won first place in our class (Manufactured Custom) at the 20th Annual Custom Bike Show in Birch Run, MI. Pretty cool.

Some of the models there agreed to pose on our bike for us, so here’s a picture of the gorgeous Jackie from Leather Works posing on our green Big Bear Choppers Sled Pro custom bike:

Jackie on our Bike

Syndicated 2008-01-21 19:07:55 from Sean Middleditch

Hair Cut

So I just got my first real hair cut in 11 years.

Me with short hair

Yeah, it’s all short now. The picture’s lighting sucks, as my apartment’s lighting sucks. What my apartment lacks in lighting it more than makes up for with pharaoh ants (I think, hard to identify a bug that size with eyes like mine and no magnifying glass).

The short hair is kinda throwing me for a loop. I don’t have a ponytail to play with while I think anymore. :(

Syndicated 2008-01-05 22:01:30 from Sean Middleditch

Moving Monday

I’m moving to my new apartment tomorrow, on New Year’s Eve. Fun fun.

Helped my very-soon-to-be ex-roommate buy the various necesseties he’ll need, like dishware and such, since I own pretty much everything in the apartment now. Also picked up some more objects d’art for the new apartment, since I’m going to have an awful lot of wall space to make interesting.

Syndicated 2007-12-31 01:15:29 from Sean Middleditch

Metacity Compositor

The new Metacity compositor in 2.21.5 is pretty sweet. It has only very simple effects (no eye-straining wobbly bullshit or workspace transition effects that just waste time), so it isn’t nearly as annoying as Compiz demos make compositing seem to be. It also made the desktop feel a little faster. The new desktop switcher is also a good deal nicer than the old one. Once an exposé-like feature is added, I think I’ll be all set with Metacity. All in all, I like it quite a bit.

Hopefully Ubuntu replaces the “low-bling desktop effects” option in the desktop effects setup with the new metacity. Compiz is a beast and it can’t even work on common setups like any machine that doesn’t support accelerated GL.

The only “bug” I’ve noticed with the new compositor is that windows sometimes get drawn to the screen before they have any content, so you see a very short flash of garbled pixel data. I’m not entirely sure if that’s a problem with Metacity, with X, or with GTK+. It’s not really critical, and I imagine it’ll be fixed in whichever layer needs it soon.

Syndicated 2007-12-22 22:40:00 from Sean Middleditch

Apartment Scare, All Good

The apartments I’m moving into, Aspen Chase in Ypsilanti, once International Place, have a very bad reputation. A very well earned, very bad reputation. The place used to be crawling with drug addicts, rapists, thieves, and other criminals, and that’s an alarmist exageration. The sex offender density for International was almost four times that of the average for tor Ypsilanti Township.

I found at all of this after making the decision to move in. Having not yet signed the lease, I was about to back out entirely. I have friends who used to live there telling me how awful it was, apartment review sites claiming it to be the most disgusting hole to live in, and neighbors who moved to my current hooker-infested (no, really, I almost ran one over last night because she jumped out in front of my truck hooking - it’s a real fucking shame that it’s illegal to run them over) told me how bad Aspen Chase was.

Having visited a few times, the place did not at all seem bad. The staff are great, the apartments are clean and recently remodeled, and I didn’t see any nasty people hanging around or here loud noise or other problems during the few hours I’ve spent looking around with friends and family.

I decided to just call the Sheriff’s Department and ask. The officer I spoke told me that the crime rate has dropped tremendously in the last year, and that while they do still get calls there, it’s no worse than anywhere else in the Township. To quote, “I wouldn’t discourage you from living there.”

Turns out that McKinley, the current owners, just bought the place a year ago, and have been fixing it up really nice like they tend to do. They like to buy crappy places and sink a bunch of money into them to make them nice, and I’m told by my mom that their reputation is impeccable.

That was a pretty big scare there for a few days, though. I was about to back out, and then I’d have been screwed on finding a place to live by the time my current lease is up.

On a worse note (unrelated to apartments), the small wart I’ve had on my right thumb under the nail is - two years, 14 cryo-surgeries, and one radio-surgey later - still there. The dermatologist told me that she gives up and won’t touch it anymore, and that I should look into getting laser surgery on it. I’ve had warts on my hands when I was a young kid, and a freeze or two later and they’d always be gone. I hadn’t had one in years until this one showed up, but it just will not go away. So now I get to look into laser surgery, which is usually for cosmetic purposes, which means it will be difficult to get health insurance to pay for it. It doesn’t help that my insurance expires this month, so if I don’t at least get the surgey billed in the next week or two, I’ll have to pay for a very expensive laser surgery out of pocket just to get rid of this stupid wart. I’m tempted to just leave it alone, since they’re supposed to go away in a couple years on their own, but given that it’s already been a couple years and it’s actually a little bigger than it was when I first noticed it, I’m going to do whatever I can to just get rid of it. I’m beyond sick of having it there, if for no other reason than it just makes me feel dirty for having it, even if it is where nobody ever notices it and it can’t spread easily.

Syndicated 2007-12-13 06:34:18 from Sean Middleditch

Creating Custom C++ Output Streams

In my younger, dumber days, I’d often write whole new classes in C++ when I had a need for output streaming, such as in a class handling a TELNET connection. Such classes required a ton of

I'm here today to tell you how not to do that, but to instead write a stream class that will work with all of the standard C++ output stream features. You might even learn a thing or two about input streams, but output streams are going to be my focus.

Note that I’m only going to touch on the basics here. C++ streams have a lot of features, most of which you won’t need to customize in the the majority of circumstances, so I’m ignoring those topics.

Introduction

Streaming output in C++ is accomplished by using the

One of the primary reasons to use a stream instead of directly writing bytes to a file is that streams allow for formatting and buffering. Formatting allows you to do something like the follow:

cout 

That will write out 123 in hexadecimal, or 7b. Without streaming, you’d have to create a byte buffer, format 123 yourself into that buffer, and then call system facilities like wite() to get your output on the screen. Kind of a pain.

C programmers will be familiar with the printf family of functions. These functions server a very similar role to the C++ streaming facilities. The above line of code, in C, could be written:

printf("%xn", 123);

The C++ streams offer several very distinct advantages over the printf family of functions, however. The first, and most widely known, is type safety. If the printf call had used the %s formatter instead of %x, then the program would likely have just crashed. The second advantage is that C++ streams have built-in support for user-controllable buffering. Buffering allows output to be stored up and sent to the OS facilities in larger chunks, which can both improve performance as well as allow for some special tricks which we’ll explore later. To provide user-controlled buffering in C, new functions which use printf functions internally must be created, and gracefully dealing with buffer overflows (that is, neither crashing nor losing output) can be a serious pain. A final advantage is that C++ streams maintain state, allowing you to more easily output a large number of identically formatted values without respecifying the format for each and every one.

The printf family of functions do have some advantages. They are, in most implementations, significantly faster than their C++ counterparts. Additionally, sometimes that “advantage” of C++ streams of maintaining state can actually be a problem, particularly if you set some state and never unset it. For example, the C++ example up above sets the number output format to hexadecimal, but never reverts it to decimal. All other output on cout will be formatted to hexadecimal until reset.

Since this is an article about C++ streams and not C string formatting, we’re going to assume that you actually want to use C++ streams and not printf, so let’s get on to the meat of creating a custom output stream.

Ostream and Streambuf

The std::ostream class does all the meat of formatting your streams. It stores the output state (like whether numbers should be displayed as decimal or hexadecimal) and processes your values to convert them into the correctly formatted output. This class is really the true core of all output formatting.

There’s absolutely no need to derive a class from std::ostream, either. The ostream class handles the formatting, but it doesn’t itself actually do anything with the output. Sure, there are derived classes like std::ofstream and std::ostringstream in the standard library, but these classes don’t actually change the behavior of std::ostream in any way. They are merely convenience wrappers that make use of a derived std::streambuf class.

All the actual work of outputing formatted data is performed by std::streambuf. Every ostream has a streambuf object associated with it. When you stream data to an ostream object, it formats the data and passes the results on to its streambuf. The streambuf then does the actual interesting work of writing the result out to your screen, into a file, or into an internal buffer. When you want to change the behavior of an output stream, what you actually need to do is make a new streambuf child class.

The std::ofstream class, for instance, creates a new std::filebuf object and associates it with the opened file. The ofstream class also offers a few other convenience methods on top of the base std::ostream, but all of these methods actually interact with the filebuf object.

To associate a streambuf object with an ostream, you can call the ostream::rdbuf() method. If called with no arguments, it returns the current streambuf. If called with a pointer to a streambuf, it sets that as the current streambuf. You can also pass a pointer to a streambuf to the constructor for an ostream. For example, let’s mimic ofstream using just ostream and filebuf.

filebuf file;
file.open("myfile.txt", ios::out);
ostream os(&file);
os 

That could behaves identically to code that uses ofstream. The only difference there is that the methods like open and close must be called on the filebuf object instead of the ostream object.

There is one catch to be wary of. The ostream class will not manage the memory for its streambuf object. That’s fine for the example above, but if you had created the filebuf object using the new operator, you would have to remember to delete the pointer yourself when you’re done.

Buffered and Unbuffered Output

There are two kinds of output you can perform using the std::streambuf class: buffered and unbuffered. Buffered output is when all data is stored temporarily in a buffer. The data is only sent to the actual output destination when the buffer fills up, or when the output stream is flushed. Unbuffered output sends all data to the output destination immediately.

When you create a new streambuf instance, it is by default unbuffered. If you wish to make it buffered, you must create a buffer for it, and then tell the streambuf about your buffer using the setp method, which is protected. So, to create a buffered streambuf object using a 100 character buffer:

class mybuf : public streambuf {
public:
  mybuf () {
    setp(buffer, buffer + sizeof(buffer));
  }

private:
  char_type buffer[100];
};

And voila! Your streambuf descendent is now buffered using your 100 character array. That’s all there is to it.

Note that buffer memory is not managed by the streambuf class. If you allocate a buffer with new, you are responsible for deleting it.

Custom Unbuffered Streams

You want to write a log stream facility that sends output both to cerr (standard error output) as well as a file, mylog.txt. It’s easy enough to do either - just stream your data to either cerr or a ofstream - but you’d rather not write each stream command twice. Writing a very simply streambuf class that performs both for you is, thankfully, quite easy.

A virtual method called xsputn is called on a streambuf whenever there is data to write. You need only override that one function to create a custom unbuffered streambuf. The function takes a pointer to an array of characters and the length of the array, and is expected to return the number of characters it was able to write. Since we’re just passing this on to a couple other streams we just return the length of the buffer given us.

// your log file, lazily declared as a global
ofstream logfile;

// logbuf forwards all output to cerr and logfile
class logbuf : public streambuf {
private:
  // write a string s of length n to standard
  // error and a log file
  int xsputn (char_type* s, streamsize n) {
    cerr.write(s, n);
    logfile.write(s, n);
    return n;
  }
};

int main () {
  // open our log file
  logfile.open("mylog.txt", ios::app);

  // create our log stream
  ostream log(new logbuf());

  // be friendly
  log 

That’s the gist of what you need, and nothing more. Pretty simple, eh? We could improve things a little further. For example, our logbuf object is leaked - we never delete it. That isn’t really vital for this example, since the memory is reclaimed at the end of the function anyhow, but we should handle it properly anyway. More importantly for our little example, however, we don’t control buffering properly. Our logbuf is unbuffered, but both cerr and logfile are buffered. We would expect the

class logbuf : public streambuf {
private:
  // flush both cerr and logfile; return 0 to
  // indicate there was no error, but we're
  // too lazy to check for errors ourselves
  int sync () {
    cerr.flush();
    logfile.flush();
    return 0;
  }

  // write a string s of length n to standard
  // error and a log file
  int xsputn (char_type* s, streamsize n) {
    cerr.write(s, n);
    logfile.write(s, n);
    return n;
  }
};

There, flushing is now supported!

I’m going take this moment to explain the char_type and streamsize types used above. streambuf::char_type is a typedef for the actual character type in use, which for streambuf would be char. The wstreambuf type is identical to streambuf, except it works with wchar_t (wide character support, for unicode), and char_type is different for that class. The streamsize type is similar in purpose to size_t - it’s just a typedef for the particular type of integer your STL implementation chose, and using streamsize makes your code portable.

Custom Buffered Streams

Unbuffered streams are great, but they’re not always what you’re looking for. Say that you are writing a network stream. You don’t want to call send() over and over for performance reasons; you’d rather buffer up your output and send it all at once. Once we set the buffer with setp, the streambuf class will do all the work of putting characters into the buffer and protecting against overruns. We don’t need to implement our own xsputn at all, since the default implementation does exactly what we want. We can simply override the sync method to take our buffer contents, write them to the socket, and then clear the buffer.

class sockbuf : public streambuf {
public:
  // initialize our sockbuf with a socket
  // descriptor, and setup a new buffer
  sockbuf (int _sockfd) : sockfd(_sockfd) {
    char_type* buf = new char_type[1024];
    setp(buf, buf + 1024);
  }

  // free our buffer
  ~sockbuf () {
    delete[] pbase();
  }

private:
  // dump our buffer to the socket and clear
  // the buffer
  int sync () {
    // for brevity's sake, not doing proper error
    // handling; we return a non-zero value(error)
    // if we failed to send the full buffer contents
    int ret = send(sockfd, pbase(), pptr() - pbase(), 0);
    if (ret != pptr() - pbase())
      return 1;
    // reset the buffer
    setp(pbase(), epptr());
    return 0;
  }

  // our socket descriptor
  int sockfd;
};

We’ve got a few new functions there. The pbase() method returns a pointer to the beginning of the buffer. The pptr() method returns the current position of the stream in the buffer. So, the number of characters in the buffer is equal to pptr() minus pbase().

Unfortunately, this little class has a problem. Our buffer is only 1024 characters long, and the data is only written out when the flush method is called on the ostream using this streambuf. When that buffer fills up, any further data we try to stream is just lost. It would be ideal if we could instead grow the buffer or try to flush the data we already have in the buffer. Let’s try growing the buffer.

When our buffer fills up, the overflow() method is called. This method takes the character that didn’t fit into the buffer as a parameter, and returns either EOF to indicate failure or any other value to indicate success. We’re just going to grow our buffer by 1024 elements and then call the standard sputc() function to add the character into the buffer.

class sockbuf : public streambuf {
public:
  // initialize our sockbuf with a socket
  // descriptor, and setup a new buffer
  sockbuf (int _sockfd) :
      sockfd(_sockfd), buf(0), buflen(1024) {
    buf = new char_type[buflen];
    setp(buf, buf + buflen);
  }

  // free our buffer
  ~sockbuf () {
    delete[] buf;
  }

private:
  // dump our buffer to the socket and
  // clear the buffer
  int sync () {
    // for brevity's sake, not doing proper error
    // handling; we return a non-zero value(error)
    // if we failed to send the full buffer contents
    int ret = send(sockfd, pbase(), pptr() - pbase(), 0);
    if (ret != pptr() - pbase())
      return 1;
    // reset the buffer
    setp(pbase(), epptr());
    return 0;
  }

  // we ran out of space, so grow
  // the buffer
  int overflow (int c) {
    // allocate a new buffer and copy our
    // current data into it, then swap it with
    // the old buffer
    char_type newbuf[buflen + 1024];
    memcpy(newbuf, buf, buflen);
    delete[] buf;
    buf = newbuf;

    // now we need to stuff c into the buffer
    sputc(c);
    return 0;
  }

  // our socket descriptor
  int sockfd;

  // our buffer
  char_type* buf;
  unsigned long buflen;
};

And there we have it. Our sockbuf class can now buffer up data until flushed without losing any data.

Complex Example

Alright, let’s go ahead and totally abuse the system now. We want to use our log class from before, but we want all of our log lines to include a date and time at the start as well as a log priority, but we don’t want to have to stream the time to log over and over. We’d like to be able to write code like this:

log 

There are a few important things going on here. First, we are setting the priority by streaming out a special priority value (e.g., DEBUG, ERROR). Note that on the third line we didn’t stream a priority, but the ERROR priority from the prior line didn’t carry over. It’s a piece of state that we’ll reset when a flush (or endl) occurs on the stream.

We could do this as an unbuffered stream. We would just write an xsputn method that wrote the time and then the log message. However, think what would happen in this example:

log 

We’d actually end up with the time and priority printed four times in the single line: once before “The,” once before the user’s name, once before ” logged,” and then a final time just before the newline. We wil need to buffer our output and then only write the time and the log once for each flush.

We’re also going to assume that flush won’t be called on our log directly, but instead we’ll always use endl. That way we know that our stream will contain a newline and we don’t need to worry about one ourself.

We’re also going to actually override ostream this time. We actually need to do that to get the priority feature to work, plus it’s kind of a pain to have to create an ostream object and then call rdbuf() on it all the time, and a custom ostream allows us to hide that in the constructor.

First, the priorities. This will just be a simple enum.

enum LogPriority {
  INFO, // regular unimportant log messages
  DEBUG, // debugging fluff
  ERROR, // it's dead, jim
};

Because it’s an enum, we can create a special

Our logbuf derived from streambuf should be fairly old news by this time. In fact, it's identical to our sockbuf above, except when sync() is called we spit out the time and the log message to cerr and a logfile ofstream, whch this time around we'll make a member. We also keep the current priority level, which defaults to INFO.

class logbuf : public streambuf {
public:
  // create a buffer and initialize our logfile
  logbuf (const char* logpath) :
      priority(INFO), buf(0), buflen(1024) {
    // create our buffer
    buf = new char_type[buflen];
    setp(buf, buf + buflen);

    // open the log file
    logfile.open(logpath, ios::app);
  }

  // free our buffer
  ~logbuf () {
    delete[] buf;
  }

  // set the priority to be used on the
  // next call to sync()
  void set_priority (LogPriority p) {
    priority = p;
  }

private:
  // spit out the time, priority, and the
  // log buffer to cerr and logfile
  int sync () {
    // nifty time formatting functions
    // from the C standard library
    time_t t = time();
    tm* tmp = localtime(&t);
    char timebuf[128];
    strftime(timebuf, sizeof(timebuf),
      "%Y-%m-%d %H:%M:%S", tmp);

    // now we stream the time, then the
    // priority, then the message
    cerr 

Well, there’s that. Now we need our customized ostream-derived class so that we can stream the LogPriority values and get the desired behavior. We’ll keep a logbuf object as a member variable, which we’ll setup as the streambuf for ostream in the constructor.

class logstream : public ostream {
public:
  // we initialize the ostream to use our logbuf
  logstream (const char* logpath) :
    ostream(&buf), logbuf(path) {}

  // set priority
  void set_priority (LogPriority pr) {
    buf.set_priority(pr);
  }

private:
  // our logbuf object
  logbuf buf;
};

// set the priority for a logstream/logbuf
// this must be a global function and not a
// member to work around C++'s type
// resolution of overloaded functions
logstream& operator

And there you have it! You can now easily create log and use logstreams. You can even have multiple such streams, giving each its own log file.

int main () {
  logstream log("logfile.txt");

  log 

Closing Thoughts

C++ streams are fairly simple to implement. We took a few liberties in the examples above with sockets and memory handling, but the core concepts of writing a custom output streambuf are there.

The complete source to the logstream example is available here.

Syndicated 2007-12-10 23:34:28 from Sean Middleditch

LLVM Development

So, I decided to go ahead and sink into LLVM and Clang. Feels good to be back in the wider development community, even if time spent on Clang is eating up paid-time for my work projects.

The Clang code is huge, and the subject material is complciated, but the code is surprisingly clean and the comments are generally fairly useful. It’s completely awesome compared to hacking on “professional” PHP scripts where the original coders didn’t understand basic concepts or understand how to write useful comments or function names.

Granted, the few tiny patches I’ve sent in to Clang have so far been not quite right, but I’m still learning the guts of how a C compiler works. There’s a big gap between understanding the various effects on code generation between using a short and a long and understanding how the compiler actually generates the the code. For example, the bug I’m currently working on has to do with padding between struct fields, which is something I knew about and something I’ve worked wirh before (reordering fields to reduce the total amount of padding), but making a compiler track that padding, calculate the correct amount based on type and architecture, and so on isn’t something I’ve ever needed to know before. Writing a generic interpreted scripting engine on a custom byte-code VM and writing a standards compliant and system ABI compatible C compiler are worlds apart.

Still, actually learning how Clang works is fairly easy, if time consuming. It’s huge, but it’s well written.

I look forward to submitting a patch for the struct padding issue I’m running into, and maybe even having that patch do everything correctly. Which might be hard, given I can only test on a small handful of architectures (x86, amd64, ppc32).

Syndicated 2007-12-10 17:11:00 from Sean Middleditch

362 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!