be93b7b4230924302d6676bf5f17139e97c7ab5a
[citadel.git] / libcitadel / lib / b64 / README
1 b64: Base64 Encoding/Decoding Routines
2 ======================================
3
4 Overview:
5 --------
6 libb64 is a library of ANSI C routines for fast encoding/decoding data into and
7 from a base64-encoded format. C++ wrappers are included, as well as the source
8 code for standalone encoding and decoding executables.
9
10 base64 consists of ASCII text, and is therefore a useful encoding for storing 
11 binary data in a text file, such as xml, or sending binary data over text-only
12 email.
13
14 References:
15 ----------
16 * Wikipedia article:
17         http://en.wikipedia.org/wiki/Base64
18 * base64, another implementation of a commandline en/decoder:
19         http://www.fourmilab.ch/webtools/base64/
20
21 Why?
22 ---
23 I did this because I need an implementation of base64 encoding and decoding,
24 without any licensing problems. Most OS implementations are released under
25 either the GNU/GPL, or a BSD-variant, which is not what I require.
26
27 Also, the chance to actually use the co-routine implementation in code is rare,
28 and its use here is fitting. I couldn't pass up the chance.
29 For more information on this technique, see "Coroutines in C", by Simon Tatham,
30 which can be found online here: 
31 http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
32
33 So then, under which license do I release this code? On to the next section...
34
35 License:
36 -------
37 This work is released under into the Public Domain.
38 It basically boils down to this: I put this work in the public domain, and you
39 can take it and do whatever you want with it.
40
41 An example of this "license" is the Creative Commons Public Domain License, a
42 copy of which can be found in the LICENSE file, and also online at
43 http://creativecommons.org/licenses/publicdomain/
44
45 Commandline Use:
46 ---------------
47 There is a new executable available, it is simply called base64.
48 It can encode and decode files, as instructed by the user.
49
50 To encode a file:
51 $ ./base64 -e filea fileb
52 fileb will now be the base64-encoded version of filea.
53
54 To decode a file:
55 $ ./base64 -d fileb filec
56 filec will now be identical to filea.
57
58 Programming:
59 -----------
60 Some C++ wrappers are provided as well, so you don't have to get your hands
61 dirty. Encoding from standard input to standard output is as simple as
62
63         #include <b64/encode.h>
64         #include <iostream>
65         int main()
66         {
67                 base64::encoder E;
68                 E.encode(std::cin, std::cout);
69                 return 0;
70         }
71
72 Both standalone executables and a static library is provided in the package,
73
74 Implementation:
75 --------------
76 It is DAMN fast, if I may say so myself. The C code uses a little trick which
77 has been used to implement coroutines, of which one can say that this
78 implementation is an example.
79
80 (To see how the libb64 codebase compares with some other BASE64 implementations
81 available, see the BENCHMARKS file)
82
83 The trick involves the fact that a switch-statement may legally cross into
84 sub-blocks. A very thorough and enlightening essay on co-routines in C, using
85 this method, can be found in the above mentioned "Coroutines in C", by Simon
86 Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
87
88 For example, an RLE decompressing routine, adapted from the article:
89 1       static int STATE = 0;
90 2       static int len, c;
91 3       switch (STATE)
92 4       {
93 5               while (1)
94 6               {
95 7                       c = getchar();
96 8                       if (c == EOF) return EOF;
97 9                       if (c == 0xFF) {
98 10                              len = getchar();
99 11                              c = getchar();
100 12                              while (len--)
101 13                              {
102 14                                      STATE = 0;
103 15                                      return c;
104 16      case 0:
105 17                              }
106 18                      } else
107 19                              STATE = 1;
108 20                              return c;
109 21      case 1:
110 22                      }
111 23              }
112 24      }
113
114 As can be seen from this example, a coroutine depends on a state variable,
115 which it sets directly before exiting (lines 14 and 119). The next time the
116 routine is entered, the switch moves control to the specific point directly
117 after the previous exit (lines 16 and 21).hands
118
119 (As an aside, in the mentioned article the combination of the top-level switch,
120 the various setting of the state, the return of a value, and the labelling of
121 the exit point is wrapped in #define macros, making the structure of the
122 routine even clearer.)
123
124 The obvious problem with any such routine is the static keyword.
125 Any static variables in a function spell doom for multithreaded applications.
126 Also, in situations where this coroutine is used by more than one other
127 coroutines, the consistency is disturbed.
128
129 What is needed is a structure for storing these variabled, which is passed to
130 the routine seperately. This obviously breaks the modularity of the function,
131 since now the caller has to worry about and care for the internal state of the
132 routine (the callee). This allows for a fast, multithreading-enabled
133 implementation, which may (obviously) be wrapped in a C++ object for ease of
134 use.
135
136 The base64 encoding and decoding functionality in this package is implemented
137 in exactly this way, providing both a high-speed high-maintanence C interface,
138 and a wrapped C++ which is low-maintanence and only slightly less performant.