📄 base64.w
字号:
%% B A S E 6 4%% by John Walker% http://www.fourmilab.ch/%% What's all this, you ask? Well, this is a "literate program",% written in the CWEB language created by Donald E. Knuth and% Silvio Levy. This file includes both the C source code for% the program and internal documentation in TeX. Processing% this file with the CTANGLE utility produces the C source file,% while the CWEAVE program emits documentation in TeX. The% current version of these programs may be downloaded from:%% http://www-cs-faculty.stanford.edu/~knuth/cweb.html%% where you will find additional information on literate% programming and examples of other programs written in this% manner.%% If you don't want to wade through all these details, don't% worry; this distribution includes a .c file already% extracted and ready to compile. If "make" complains that it% can't find "ctangle" or "cweave", just "touch *.c"% and re-make--apparently the process of extracting the files% from the archive messed up the date and time, misleading% make into believing it needed to rebuild those files.@** Introduction.\vskip 15pt\centerline{\ttitlefont BASE64}\vskip 10pt\centerline{\titlefont Encode or decode file as MIME base64 (RFC 1341)}\vskip 15pt\centerline{by John Walker}\centerline{\.{http://www.fourmilab.ch/}}\vskip 15pt\centerline{This program is in the public domain.}\vskip 15pt\centerline{EBCDIC support courtesy of Christian.Ferrari@@fccrt.it, 2000-12-20.}\vskip 30pt@d REVDATE "21st February 2001"@** Program global context.@d TRUE 1@d FALSE 0@d LINELEN 72 /* Encoded line length (max 76) */@d MAXINLINE 256 /* Maximum input line length */@c#include "config.h" /* System-dependent configuration */@h@<System include files@>@/@<Windows-specific include files@>@/@<Global variables@>@/@ We include the following POSIX-standard C library files. Conditionals based on a probe of the system by the \.{configure} program allow us to cope with the peculiarities of specific systems. @<System include files@>=#include <stdio.h>#include <stdlib.h>#include <ctype.h>#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#ifdef HAVE_GETOPT#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#else#include "getopt.h" /* No system \.{getopt}--use our own */#endif@ The following include files are needed in WIN32 builds to permit setting already-open I/O streams to binary mode.@<Windows-specific include files@>=#ifdef _WIN32#define FORCE_BINARY_IO#include <io.h>#include <fcntl.h>#endif@ These variables are global to all procedures; many are used as ``hidden arguments'' to functions in order to simplify calling sequences.@<Global variables@>=typedef unsigned char byte; /* Byte type */static FILE *fi; /* Input file */static FILE *fo; /* Output file */static byte iobuf[MAXINLINE]; /* I/O buffer */static int iolen = 0; /* Bytes left in I/O buffer */static int iocp = MAXINLINE; /* Character removal pointer */static int ateof = FALSE; /* EOF encountered */static byte dtable[256]; /* Encode / decode table */static int linelength = 0; /* Length of encoded output line */static char eol[] = "\r\n"; /* End of line sequence */static int errcheck = TRUE; /* Check decode input for errors ? */@** Input/output functions.@ Procedure |inbuf|fills the input buffer with data from the input stream |fi|.@cstatic int inbuf(void){ int l; if (ateof) { return FALSE; } l = fread(iobuf, 1, MAXINLINE, fi); /* Read input buffer */ if (l <= 0) { if (ferror(fi)) { exit(1); } ateof = TRUE; return FALSE; } iolen = l; iocp = 0; return TRUE;}@ Procedure |inchar|returns the next character from the input line. At end of line,it calls |inbuf| to read the next line, returning |EOF| at endof file.@cstatic int inchar(void){ if (iocp >= iolen) { if (!inbuf()) { return EOF; } } return iobuf[iocp++];}@ Procedure |insig|returns the next significant input character, ignoringwhite space and control characters. This procedure uses|inchar| to read the input stream and returns |EOF| whenthe end of the input file is reached.@cstatic int insig(void){ int c; while (TRUE) { c = inchar(); if (c == EOF || (c > ' ')) { return c; } }}@ Procedure |ochar|outputs an encoded character, inserting line breaksas required so that no line exceeds |LINELEN|characters.@cstatic void ochar(int c){ if (linelength >= LINELEN) { if (fputs(eol, fo) == EOF) { exit(1); } linelength = 0; } if (putc(((byte) c), fo) == EOF) { exit(1); } linelength++;}@** Encoding.Procedure |encode|encodes the binary file opened as |fi| into base64, writingthe output to |fo|.@cstatic void encode(void){ int i, hiteof = FALSE; @<initialise encoding table@>;@\ while (!hiteof) { byte igroup[3], ogroup[4]; int c, n; igroup[0] = igroup[1] = igroup[2] = 0; for (n = 0; n < 3; n++) { c = inchar(); if (c == EOF) { hiteof = TRUE; break; } igroup[n] = (byte) c; } if (n > 0) { ogroup[0] = dtable[igroup[0] >> 2]; ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; ogroup[3] = dtable[igroup[2] & 0x3F]; /* Replace characters in output stream with "=" pad characters if fewer than three characters were read from the end of the input stream. */ if (n < 3) { ogroup[3] = '='; if (n < 2) { ogroup[2] = '='; } } for (i = 0; i < 4; i++) { ochar(ogroup[i]); } } } if (fputs(eol, fo) == EOF) { exit(1); }}@ Procedure |initialise_encoding_table| fills the binary encoding table with the characters the 6 bit values are mapped into. The curious and disparate sequences used to fill this table permit this code to work both on ASCII and EBCDIC systems, the latter thanks to Ch.F. In EBCDIC systems character codes for letters are not consecutive; the initialisation must be split to accommodate the EBCDIC consecutive letters: \centerline{ A--I J--R S--Z a--i j--r s--z} This code works on ASCII as well as EBCDIC systems.@<initialise encoding table@>= for (i = 0; i < 9; i++) { dtable[i] = 'A' + i; dtable[i + 9] = 'J' + i; dtable[26 + i] = 'a' + i; dtable[26 + i + 9] = 'j' + i; } for (i = 0; i < 8; i++) { dtable[i + 18] = 'S' + i; dtable[26 + i + 18] = 's' + i; } for (i = 0; i < 10; i++) { dtable[52 + i] = '0' + i; } dtable[62] = '+'; dtable[63] = '/';@** Decoding.Procedure |decode| decodes a base64 encoded stream from|fi| and emits the binary result on |fo|.@cstatic void decode(void){ int i; @<Initialise decode table@>; while (TRUE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -