So. I’m glad there’s a PNG reference library in libpng, and that it’s open sores, and it’s free, and all that. But the folks that originally designed it were complete idiots when it came to API design. For some reason, in this C library, they decided not to follow the time-honored pattern of returning error codes from functions. Instead, they designed an API which uses setjmp to set up error callbacks, and then it longjmps to them as necessary. To quote the authors:
The motivation behind using setjmp() and longjmp() is the C++ throw and catch exception handling methods. This makes the code much easier to write, as there is no need to check every return code of every function call. However, there are some uncertainties about the status of local variables after a longjmp, so the user may want to be careful about doing anything after setjmp returns non-zero besides returning itself.
So, we’ve got this language. Let’s call it C for the sake of argument, since that’s its name. It doesn’t have exceptions. So, rather than follow the time-honored tradition of writing C libraries, the libpng folks decided it was a brilliant move to try to emulate exceptions using a sophisticated version of GOTO. Let’s take a look at a choice excerpt from the man pages for longjmp:
longjmp() and siglongjmp() make programs hard to understand and maintain. If possible an alternative should be used.
Yeah. Right there. Your “makes it easier” approach just made things a lot harder. Why? Because, from time to time, people want to use C libraries from C++. You know, a language that actually has exceptions. A language that really doesn’t get along well with things like setjmp() and longjmp(). If we just had a nice, standard, error-returning library in C that works like every other library in C, we wouldn’t be in trouble. Write a class that wraps up the C functions, thirty minutes later your job is done. But, no, now we have a giant mess on our hands.
The thing that disgusts me is libpng leverages zlib, a perfectly well-designed C library that happens to also be very easy to use from C++. The designers of libpng had to intentionally ignore this elegantly written library (well, we’re talking elegant in C terms, it is C after all), and make this complete mess of a solution instead.
I know, I know. It’s open source, the PNG format is an open standard, I can just roll my own PNG library and I shouldn’t complain, the code is free, after all. Yes, you’re right. No, that’s not really an option I have right now.
Moral of the story is there are a number of patterns and paradigms for your particular programming language. If you try to ignore them and be clever, do it for your little experimental projects, and that’s fine, but there’s a way certain ways of things have evolved over time. There’s something to be said for trying to argue against the “that’s the way it’s always been done” philosophies (this argument pisses me off all the time, and I run into it all the time), but there are a lot of things that are always done the same way for a very good reason: it may well be the best way to solve that particular problem for a number of reasons that aren’t immediately obvious. Don’t try to be clever just for the sake of being clever.