The Go Programming Language

Source file src/pkg/encoding/base64/base64.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// Package base64 implements base64 encoding as specified by RFC 4648.
     6	package base64
     7	
     8	import (
     9		"io"
    10		"os"
    11		"strconv"
    12	)
    13	
    14	/*
    15	 * Encodings
    16	 */
    17	
    18	// An Encoding is a radix 64 encoding/decoding scheme, defined by a
    19	// 64-character alphabet.  The most common encoding is the "base64"
    20	// encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
    21	// (RFC 1421).  RFC 4648 also defines an alternate encoding, which is
    22	// the standard encoding with - and _ substituted for + and /.
    23	type Encoding struct {
    24		encode    string
    25		decodeMap [256]byte
    26	}
    27	
    28	const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    29	const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
    30	
    31	// NewEncoding returns a new Encoding defined by the given alphabet,
    32	// which must be a 64-byte string.
    33	func NewEncoding(encoder string) *Encoding {
    34		e := new(Encoding)
    35		e.encode = encoder
    36		for i := 0; i < len(e.decodeMap); i++ {
    37			e.decodeMap[i] = 0xFF
    38		}
    39		for i := 0; i < len(encoder); i++ {
    40			e.decodeMap[encoder[i]] = byte(i)
    41		}
    42		return e
    43	}
    44	
    45	// StdEncoding is the standard base64 encoding, as defined in
    46	// RFC 4648.
    47	var StdEncoding = NewEncoding(encodeStd)
    48	
    49	// URLEncoding is the alternate base64 encoding defined in RFC 4648.
    50	// It is typically used in URLs and file names.
    51	var URLEncoding = NewEncoding(encodeURL)
    52	
    53	/*
    54	 * Encoder
    55	 */
    56	
    57	// Encode encodes src using the encoding enc, writing
    58	// EncodedLen(len(src)) bytes to dst.
    59	//
    60	// The encoding pads the output to a multiple of 4 bytes,
    61	// so Encode is not appropriate for use on individual blocks
    62	// of a large data stream.  Use NewEncoder() instead.
    63	func (enc *Encoding) Encode(dst, src []byte) {
    64		if len(src) == 0 {
    65			return
    66		}
    67	
    68		for len(src) > 0 {
    69			dst[0] = 0
    70			dst[1] = 0
    71			dst[2] = 0
    72			dst[3] = 0
    73	
    74			// Unpack 4x 6-bit source blocks into a 4 byte
    75			// destination quantum
    76			switch len(src) {
    77			default:
    78				dst[3] |= src[2] & 0x3F
    79				dst[2] |= src[2] >> 6
    80				fallthrough
    81			case 2:
    82				dst[2] |= (src[1] << 2) & 0x3F
    83				dst[1] |= src[1] >> 4
    84				fallthrough
    85			case 1:
    86				dst[1] |= (src[0] << 4) & 0x3F
    87				dst[0] |= src[0] >> 2
    88			}
    89	
    90			// Encode 6-bit blocks using the base64 alphabet
    91			for j := 0; j < 4; j++ {
    92				dst[j] = enc.encode[dst[j]]
    93			}
    94	
    95			// Pad the final quantum
    96			if len(src) < 3 {
    97				dst[3] = '='
    98				if len(src) < 2 {
    99					dst[2] = '='
   100				}
   101				break
   102			}
   103	
   104			src = src[3:]
   105			dst = dst[4:]
   106		}
   107	}
   108	
   109	// EncodeToString returns the base64 encoding of src.
   110	func (enc *Encoding) EncodeToString(src []byte) string {
   111		buf := make([]byte, enc.EncodedLen(len(src)))
   112		enc.Encode(buf, src)
   113		return string(buf)
   114	}
   115	
   116	type encoder struct {
   117		err  os.Error
   118		enc  *Encoding
   119		w    io.Writer
   120		buf  [3]byte    // buffered data waiting to be encoded
   121		nbuf int        // number of bytes in buf
   122		out  [1024]byte // output buffer
   123	}
   124	
   125	func (e *encoder) Write(p []byte) (n int, err os.Error) {
   126		if e.err != nil {
   127			return 0, e.err
   128		}
   129	
   130		// Leading fringe.
   131		if e.nbuf > 0 {
   132			var i int
   133			for i = 0; i < len(p) && e.nbuf < 3; i++ {
   134				e.buf[e.nbuf] = p[i]
   135				e.nbuf++
   136			}
   137			n += i
   138			p = p[i:]
   139			if e.nbuf < 3 {
   140				return
   141			}
   142			e.enc.Encode(e.out[0:], e.buf[0:])
   143			if _, e.err = e.w.Write(e.out[0:4]); e.err != nil {
   144				return n, e.err
   145			}
   146			e.nbuf = 0
   147		}
   148	
   149		// Large interior chunks.
   150		for len(p) >= 3 {
   151			nn := len(e.out) / 4 * 3
   152			if nn > len(p) {
   153				nn = len(p)
   154			}
   155			nn -= nn % 3
   156			if nn > 0 {
   157				e.enc.Encode(e.out[0:], p[0:nn])
   158				if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil {
   159					return n, e.err
   160				}
   161			}
   162			n += nn
   163			p = p[nn:]
   164		}
   165	
   166		// Trailing fringe.
   167		for i := 0; i < len(p); i++ {
   168			e.buf[i] = p[i]
   169		}
   170		e.nbuf = len(p)
   171		n += len(p)
   172		return
   173	}
   174	
   175	// Close flushes any pending output from the encoder.
   176	// It is an error to call Write after calling Close.
   177	func (e *encoder) Close() os.Error {
   178		// If there's anything left in the buffer, flush it out
   179		if e.err == nil && e.nbuf > 0 {
   180			e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
   181			e.nbuf = 0
   182			_, e.err = e.w.Write(e.out[0:4])
   183		}
   184		return e.err
   185	}
   186	
   187	// NewEncoder returns a new base64 stream encoder.  Data written to
   188	// the returned writer will be encoded using enc and then written to w.
   189	// Base64 encodings operate in 4-byte blocks; when finished
   190	// writing, the caller must Close the returned encoder to flush any
   191	// partially written blocks.
   192	func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
   193		return &encoder{enc: enc, w: w}
   194	}
   195	
   196	// EncodedLen returns the length in bytes of the base64 encoding
   197	// of an input buffer of length n.
   198	func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
   199	
   200	/*
   201	 * Decoder
   202	 */
   203	
   204	type CorruptInputError int64
   205	
   206	func (e CorruptInputError) String() string {
   207		return "illegal base64 data at input byte " + strconv.Itoa64(int64(e))
   208	}
   209	
   210	// decode is like Decode but returns an additional 'end' value, which
   211	// indicates if end-of-message padding was encountered and thus any
   212	// additional data is an error.  decode also assumes len(src)%4==0,
   213	// since it is meant for internal use.
   214	func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err os.Error) {
   215		for i := 0; i < len(src)/4 && !end; i++ {
   216			// Decode quantum using the base64 alphabet
   217			var dbuf [4]byte
   218			dlen := 4
   219	
   220		dbufloop:
   221			for j := 0; j < 4; j++ {
   222				in := src[i*4+j]
   223				if in == '=' && j >= 2 && i == len(src)/4-1 {
   224					// We've reached the end and there's
   225					// padding
   226					if src[i*4+3] != '=' {
   227						return n, false, CorruptInputError(i*4 + 2)
   228					}
   229					dlen = j
   230					end = true
   231					break dbufloop
   232				}
   233				dbuf[j] = enc.decodeMap[in]
   234				if dbuf[j] == 0xFF {
   235					return n, false, CorruptInputError(i*4 + j)
   236				}
   237			}
   238	
   239			// Pack 4x 6-bit source blocks into 3 byte destination
   240			// quantum
   241			switch dlen {
   242			case 4:
   243				dst[i*3+2] = dbuf[2]<<6 | dbuf[3]
   244				fallthrough
   245			case 3:
   246				dst[i*3+1] = dbuf[1]<<4 | dbuf[2]>>2
   247				fallthrough
   248			case 2:
   249				dst[i*3+0] = dbuf[0]<<2 | dbuf[1]>>4
   250			}
   251			n += dlen - 1
   252		}
   253	
   254		return n, end, nil
   255	}
   256	
   257	// Decode decodes src using the encoding enc.  It writes at most
   258	// DecodedLen(len(src)) bytes to dst and returns the number of bytes
   259	// written.  If src contains invalid base64 data, it will return the
   260	// number of bytes successfully written and CorruptInputError.
   261	func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
   262		if len(src)%4 != 0 {
   263			return 0, CorruptInputError(len(src) / 4 * 4)
   264		}
   265	
   266		n, _, err = enc.decode(dst, src)
   267		return
   268	}
   269	
   270	// DecodeString returns the bytes represented by the base64 string s.
   271	func (enc *Encoding) DecodeString(s string) ([]byte, os.Error) {
   272		dbuf := make([]byte, enc.DecodedLen(len(s)))
   273		n, err := enc.Decode(dbuf, []byte(s))
   274		return dbuf[:n], err
   275	}
   276	
   277	type decoder struct {
   278		err    os.Error
   279		enc    *Encoding
   280		r      io.Reader
   281		end    bool       // saw end of message
   282		buf    [1024]byte // leftover input
   283		nbuf   int
   284		out    []byte // leftover decoded output
   285		outbuf [1024 / 4 * 3]byte
   286	}
   287	
   288	func (d *decoder) Read(p []byte) (n int, err os.Error) {
   289		if d.err != nil {
   290			return 0, d.err
   291		}
   292	
   293		// Use leftover decoded output from last read.
   294		if len(d.out) > 0 {
   295			n = copy(p, d.out)
   296			d.out = d.out[n:]
   297			return n, nil
   298		}
   299	
   300		// Read a chunk.
   301		nn := len(p) / 3 * 4
   302		if nn < 4 {
   303			nn = 4
   304		}
   305		if nn > len(d.buf) {
   306			nn = len(d.buf)
   307		}
   308		nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 4-d.nbuf)
   309		d.nbuf += nn
   310		if d.nbuf < 4 {
   311			return 0, d.err
   312		}
   313	
   314		// Decode chunk into p, or d.out and then p if p is too small.
   315		nr := d.nbuf / 4 * 4
   316		nw := d.nbuf / 4 * 3
   317		if nw > len(p) {
   318			nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
   319			d.out = d.outbuf[0:nw]
   320			n = copy(p, d.out)
   321			d.out = d.out[n:]
   322		} else {
   323			n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
   324		}
   325		d.nbuf -= nr
   326		for i := 0; i < d.nbuf; i++ {
   327			d.buf[i] = d.buf[i+nr]
   328		}
   329	
   330		if d.err == nil {
   331			d.err = err
   332		}
   333		return n, d.err
   334	}
   335	
   336	// NewDecoder constructs a new base64 stream decoder.
   337	func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
   338		return &decoder{enc: enc, r: r}
   339	}
   340	
   341	// DecodedLen returns the maximum length in bytes of the decoded data
   342	// corresponding to n bytes of base64-encoded data.
   343	func (enc *Encoding) DecodedLen(n int) int { return n / 4 * 3 }

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.