Function: base64-decode-region
base64-decode-region is an interactive function defined in fns.c.
Signature
(base64-decode-region BEG END &optional BASE64URL)
Documentation
Base64-decode the region between BEG and END.
Return the length of the decoded data.
Note that after calling this function, the data in the region will
represent bytes, not text. If you want to end up with text, you have
to call decode-coding-region afterwards with an appropriate coding
system.
If the region can't be decoded, signal an error and don't modify the buffer. Optional third argument BASE64URL determines whether to use the URL variant of the base 64 encoding, as defined in RFC 4648.
Probably introduced at or before Emacs version 20.4.
Key Bindings
Source Code
// Defined in /usr/src/emacs/src/fns.c
{
ptrdiff_t ibeg, iend, length, allength;
char *decoded;
ptrdiff_t old_pos = PT;
ptrdiff_t decoded_length;
ptrdiff_t inserted_chars;
bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
USE_SAFE_ALLOCA;
validate_region (&beg, &end);
ibeg = CHAR_TO_BYTE (XFIXNAT (beg));
iend = CHAR_TO_BYTE (XFIXNAT (end));
length = iend - ibeg;
/* We need to allocate enough room for decoding the text. If we are
working on a multibyte buffer, each decoded code may occupy at
most two bytes. */
allength = multibyte ? length * 2 : length;
decoded = SAFE_ALLOCA (allength);
move_gap_both (XFIXNAT (beg), ibeg);
decoded_length = base64_decode_1 ((char *) BYTE_POS_ADDR (ibeg),
decoded, length, !NILP (base64url),
multibyte, &inserted_chars);
if (decoded_length > allength)
emacs_abort ();
if (decoded_length < 0)
{
/* The decoding wasn't possible. */
error ("Invalid base64 data");
}
/* Now we have decoded the region, so we insert the new contents
and delete the old. (Insert first in order to preserve markers.) */
TEMP_SET_PT_BOTH (XFIXNAT (beg), ibeg);
insert_1_both (decoded, inserted_chars, decoded_length, 0, 1, 0);
signal_after_change (XFIXNAT (beg), 0, inserted_chars);
SAFE_FREE ();
/* Delete the original text. */
del_range_both (PT, PT_BYTE, XFIXNAT (end) + inserted_chars,
iend + decoded_length, 1);
/* If point was outside of the region, restore it exactly; else just
move to the beginning of the region. */
if (old_pos >= XFIXNAT (end))
old_pos += inserted_chars - (XFIXNAT (end) - XFIXNAT (beg));
else if (old_pos > XFIXNAT (beg))
old_pos = XFIXNAT (beg);
SET_PT (old_pos > ZV ? ZV : old_pos);
return make_fixnum (inserted_chars);
}