This is part 5 of a fast paced C++ tutorial for programmers familiar with high level languages like Perl and Python.
Beyond the C++ STL
In the previous C++ tutorials, all examples were restricted to the C++ Standard Templates Library (STL), which is part of every ANSI C++ compliant compiler environment, and which we can take for granted.
Unfortunately, the STL doesn’t include classes for many popular areas, like:
- GUI Frameworks
This is intentional: because C++ is a superset of C, C++ programmers could just as easily call external C or C++ libraries (e.g. Berkeley Sockets API for networking, OpenSSL for Crypto, C bindings for SQLite3, PostgreSQL, MySQL, … for database connectivity, SAX and DOM for XML parsing, and various C++ GUI frameworks like Qt, wxWidgets, and so on.
C++ designers didn’t want to impose a default standard for all those areas of application: C++ and the STL’s philosophy is distinctly different from Java’s which includes and therefore standardizes a lot of different APIs.
So, as C++ programmers, we’re confronted with a series of choices regarding external libraries. Which library is best suited for networking? For database connectivity?…
As firm believers in Open Source Software (OSS), we eliminate closed-source and proprietary libraries right from the start (feel free to use one, if need be). Furthermore, we eliminate libraries that are not portable across platforms: it just doesn’t make sense to develop against a Windows-only API if you want to port your application to Linux later, or vice-versa, right?
There are many cross-platform OSS C++ libraries out there, some of them highly specialized, others broad in scope and size. The following “generalist” libraries are interesting from the point of view of a general application developer:
- Boost: a collection of C++ libraries designed by many members of the C++ standards committee with the intent to include the best of them in revised versions of the C++ Standard.
- POCO: a set of portable C++ components that aims to close many gaps left open by the STL.
- Qt: A powerful, cross-platform framework of C++ classes for GUI development.
In all cases, before using an external library, it is necessary to download, compile and install it both on the development and on the target machine. In this tutorial, we’ll explore a couple of classes from the POCO library, so if it isn’t already installed on your system, you’ll need to fetch it from its web site, and install it.
Base64 encoding and decoding files with POCO
To transmit files over a channel that is not 8-bit clean (e.g. UUCP, old SMTP, NNTP etc…), it is necessary to encode binary files in such a way that only some characters are being used. A long time, ago, people used to uuencode(1) and uudecode(1) such files, but today, we would Base64-encode and -decode them.
On some systems (like FreeBSD), we can use the utilities b64encode and b64decode, that are already part of the system, to achieve the job. But on most other systems, we need to roll our own Base64 encoders and decoders.
Fortunately, POCO provides the classes
Poco::Base64Decoder to do the job.
Base-64 encoding a file: b64encode.cpp
This is one possible implementation of b64encode using the Poco::Base64Encoder class:
This is how to compile this program:
The program is not really that much different from copy4.cpp of the previous tutorial, which was, in a nutshell:
The only difference is that we copy the output to b64out, which wraps the
std::ofstream ofs in a
Poco::Base64Encoder, and use b64out as the destination of the
This is the result of Base64-encoding some big file:
As you can see, the base-64 encoded file is, as expected, larger. We can also peek into (the beginning) of both files:
We see that the second file contains only printable characters.
The reverse operation is Base-64 decoding a file. Instead of
Poco::Base64Encoder, we simply use a Poco::Base64Decoder, like this:
This is, again, our file copy program, idiomatic version with
streambuf_iterators. In b64encode we wrapped ofs with
Poco::Base64Encoder. Here, we wrapped ifs with
Poco::Base64Decoder, resulting in an input stream b64in.
Now, let’s Base64-decode the file we’ve previously Base64-encoded:
Of course, we’ve got the very same file that we’ve encoded previously.
Base64-encoding and -decoding strings: b64strings.cpp
Suppose we don’t want to Base-64 encode whole files, but only
std::strings. One example could be that we want to compose Base64-encoded e-mail messages from some data that the user entered in a GUI element.
We could re-use
Poco::Base64Decoder to transform strings, but there’s a little problem here: both classes need output- und input streams, respectively, and not strings! However, the signature of the functions we need are:
Fortunately, we can easily transform a string to an input or output stream with
std::ostringstream from <sstream>. toBase64 could look like this:
and fromBase64 would be:
Here’s one possible main program:
Compling and running it:
To overcome the (intentional) limitations of the C++ STL, it is necessary to use external libraries. We distinguish between closed-source and open-source libraries, between highly specialized and broad scope libraries, and between platform-specific and cross-platform libraries.
Good libraries include Boost, Poco, and Qt, but they are by no means the only ones. C++ isn’t Java: the standard doesn’t define what external libraries are best suited for your needs. The choice is yours to make.
As an example, we’ve used the input stream adapter
Poco::Base64Encode from the POCO library to Base64-encode files (or streams, more generally), and
Poco::Base64Decode to Base64-decode files (or streams). We’ve seen how to make use of
std::ostringstring in combination with the above mentioned POCO classes, to Base64-encode and Base64-decode
Basically, we’re simply plumbing well-tested code components together and don’t reinvent the wheel.