Replaced libb64-1.2.1 with cbase64-1.0

This commit is contained in:
Jordan Cristiano 2015-07-09 20:52:06 -04:00
parent 87a3d645e4
commit ef50be7054
13 changed files with 294 additions and 368 deletions

View File

@ -1,8 +1,10 @@
#include "jsonfile.h" #include "jsonfile.h"
#include "b64/encode.h"
#include <cstdlib> #include <cstdlib>
#define CBASE64_IMPLEMENTATION
#include "cbase64/cbase64.h"
namespace base namespace base
{ {
JsonWriterFile::JsonWriterFile(FILE* fp, char* buffer, std::size_t length): JsonWriterFile::JsonWriterFile(FILE* fp, char* buffer, std::size_t length):
@ -164,29 +166,28 @@ namespace base
auto& writer = m_writer; auto& writer = m_writer;
writer.String(name); writer.String(name);
base64::base64_encodestate state; cbase64_encodestate state;
base64::base64_init_encodestate(&state); cbase64_init_encodestate(&state);
state.flags = base64::BASE64_ENC_NO_NEWLINE_TERM;
const std::size_t numBytes = ((numBits + 7) >> 3); const std::size_t numBytes = ((numBits + 7) >> 3);
const int encodedLenMax = base64::base64_calc_buffer_length(numBytes, &state); const int encodedLength = cbase64_calc_encoded_length(numBytes);
char* const encoded = (char*)calloc(encodedLenMax, 1); char* const encoded = (char*)malloc(encodedLength);
char* encodedCurOut = encoded; char* encodedCurOut = encoded;
const std::size_t numTrailingBits = (numBits & 7); const std::size_t numTrailingBits = (numBits & 7);
if (numTrailingBits > 0) if (numTrailingBits > 0)
{ {
const std::size_t numBytesWithoutBits = (numBits >> 3); const std::size_t numBytesWithoutBits = (numBits >> 3);
encodedCurOut += base64::base64_encode_block((const char*)data, numBytesWithoutBits, encodedCurOut, &state); encodedCurOut += cbase64_encode_block(data, numBytesWithoutBits, encodedCurOut, &state);
const char lastByteClean = data[numBytesWithoutBits] & ~(0xFF >> numTrailingBits); const unsigned char lastByteClean = data[numBytesWithoutBits] & ~(0xFF >> numTrailingBits);
encodedCurOut += base64::base64_encode_block(&lastByteClean, 1, encodedCurOut, &state); encodedCurOut += cbase64_encode_block(&lastByteClean, 1, encodedCurOut, &state);
} }
else else
{ {
encodedCurOut += base64::base64_encode_block((const char*)data, numBytes, encodedCurOut, &state); encodedCurOut += cbase64_encode_block(data, numBytes, encodedCurOut, &state);
} }
encodedCurOut += base64::base64_encode_blockend(encodedCurOut, &state); encodedCurOut += cbase64_encode_blockend(encodedCurOut, &state);
writer.String(encoded, encodedCurOut - encoded); writer.String(encoded, encodedCurOut - encoded);
free(encoded); free(encoded);

View File

@ -1,3 +1,12 @@
cbase64: Base64 Encoding/Decoding Routines
======================================
Authors:
-------
Jordan Cristiano
libb64: Base64 Encoding/Decoding Routines libb64: Base64 Encoding/Decoding Routines
====================================== ======================================

View File

@ -1,6 +1,28 @@
b64: Base64 Encoding/Decoding Routines cbase64: Base64 Encoding/Decoding Routines
====================================== ======================================
Forked from libb64-1.2.1.
* Removed c++ helpers
* Made header only
* Added output length calculation functions
* Removed chars per line limit
* Removed ending newline
### Usage
```
#define CBASE64_IMPLEMENTATION
```
before you include this file in *one* C or C++ file to create the implementation.
```
// i.e. it should look like this:
#include ...
#include ...
#include ...
#define CBASE64_IMPLEMENTATION
#include "cbase64.h"
```
Overview: Overview:
-------- --------
libb64 is a library of ANSI C routines for fast encoding/decoding data into and libb64 is a library of ANSI C routines for fast encoding/decoding data into and
@ -60,6 +82,7 @@ Programming:
Some C++ wrappers are provided as well, so you don't have to get your hands Some C++ wrappers are provided as well, so you don't have to get your hands
dirty. Encoding from standard input to standard output is as simple as dirty. Encoding from standard input to standard output is as simple as
```
#include <b64/encode.h> #include <b64/encode.h>
#include <iostream> #include <iostream>
int main() int main()
@ -68,6 +91,7 @@ dirty. Encoding from standard input to standard output is as simple as
E.encode(std::cin, std::cout); E.encode(std::cin, std::cout);
return 0; return 0;
} }
```
Both standalone executables and a static library is provided in the package, Both standalone executables and a static library is provided in the package,
@ -91,6 +115,7 @@ this method, can be found in the above mentioned "Coroutines in C", by Simon
Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
For example, an RLE decompressing routine, adapted from the article: For example, an RLE decompressing routine, adapted from the article:
```
1 static int STATE = 0; 1 static int STATE = 0;
2 static int len, c; 2 static int len, c;
3 switch (STATE) 3 switch (STATE)
@ -115,6 +140,7 @@ For example, an RLE decompressing routine, adapted from the article:
22 } 22 }
23 } 23 }
24 } 24 }
```
As can be seen from this example, a coroutine depends on a state variable, As can be seen from this example, a coroutine depends on a state variable,
which it sets directly before exiting (lines 14 and 119). The next time the which it sets directly before exiting (lines 14 and 119). The next time the

View File

@ -0,0 +1,245 @@
/* cbase64 - public domain base64 encoder/decoder
Do this:
#define CBASE64_IMPLEMENTATION
before you include this file in *one* C or C++ file to create the implementation.
// i.e. it should look like this:
#include ...
#include ...
#include ...
#define CBASE64_IMPLEMENTATION
#include "cbase64.h"
*/
#ifndef CBASE64_H
#define CBASE64_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
step_A, step_B, step_C, step_D
} cbase64_step;
typedef struct
{
cbase64_step step;
unsigned char result;
} cbase64_encodestate;
typedef struct
{
cbase64_step step;
char result;
} cbase64_decodestate;
void cbase64_init_encodestate(cbase64_encodestate* state_in);
void cbase64_init_decodestate(cbase64_decodestate* state_in);
unsigned int cbase64_calc_encoded_length(unsigned int length_in);
unsigned int cbase64_calc_decoded_length(const char* code_in, unsigned int length_in);
unsigned int cbase64_encode_block(const unsigned char* data_in, unsigned int length_in,
char* code_out, cbase64_encodestate* state_in);
unsigned int cbase64_decode_block(const char* code_in, unsigned int length_in,
unsigned char* data_out, cbase64_decodestate* state_in);
unsigned int cbase64_encode_blockend(char* code_out, cbase64_encodestate* state_in);
#ifdef __cplusplus
}
#endif
#endif // CBASE64_H
#ifdef CBASE64_IMPLEMENTATION
char cbase64__encode_value(unsigned char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
return encoding[(int)value_in];
}
char cbase64__decode_value(char value_in)
{
static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static const char decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in >= decoding_size) return -1;
return decoding[(int)value_in];
}
void cbase64_init_encodestate(cbase64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = '\0';
}
void cbase64_init_decodestate(cbase64_decodestate* state_in)
{
state_in->step = step_A;
state_in->result = '\0';
}
unsigned int cbase64_calc_encoded_length(unsigned int length_in)
{
return 4 * (length_in / 3) + ((length_in % 3 != 0) ? 4 : 0);
}
unsigned int cbase64_calc_decoded_length(const char* code_in, unsigned int length_in)
{
if (length_in == 0 || ((length_in & 3) != 0))
{
return 0;
}
const char secondlast = code_in[length_in - 2];
const char last = code_in[length_in - 1];
return 3 * (length_in / 4) - (secondlast == '=') - (last == '=');
}
unsigned int cbase64_encode_block(const unsigned char* data_in, unsigned int length_in,
char* code_out, cbase64_encodestate* state_in)
{
const unsigned char* datachar = data_in;
const unsigned char* const datatextend = data_in + length_in;
char* codechar = code_out;
unsigned char result = state_in->result;
unsigned char fragment;
switch (state_in->step)
{
while (1)
{
case step_A:
if (datachar == datatextend)
{
state_in->step = step_A;
state_in->result = result;
return codechar - code_out;
}
fragment = *datachar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = cbase64__encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (datachar == datatextend)
{
state_in->step = step_B;
state_in->result = result;
return codechar - code_out;
}
fragment = *datachar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = cbase64__encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (datachar == datatextend)
{
state_in->step = step_C;
state_in->result = result;
return codechar - code_out;
}
fragment = *datachar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = cbase64__encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = cbase64__encode_value(result);
}
}
// control should not reach here
return codechar - code_out;
}
unsigned int cbase64_decode_block(const char* code_in, unsigned int length_in,
unsigned char* data_out, cbase64_decodestate* state_in)
{
const char* codechar = code_in;
const char* const codeend = code_in + length_in;
unsigned char* datachar = data_out;
char fragment;
*datachar = state_in->result;
switch (state_in->step)
{
while (1)
{
case step_A:
do {
if (codechar == codeend)
{
state_in->step = step_A;
state_in->result = *datachar;
return datachar - data_out;
}
fragment = cbase64__decode_value(*codechar++);
} while (fragment < 0);
*datachar = (fragment & 0x03f) << 2;
case step_B:
do {
if (codechar == codeend)
{
state_in->step = step_B;
state_in->result = *datachar;
return datachar - data_out;
}
fragment = cbase64__decode_value(*codechar++);
} while (fragment < 0);
*datachar++ |= (fragment & 0x030) >> 4;
*datachar = (fragment & 0x00f) << 4;
case step_C:
do {
if (codechar == codeend)
{
state_in->step = step_C;
state_in->result = *datachar;
return datachar - data_out;
}
fragment = cbase64__decode_value(*codechar++);
} while (fragment < 0);
*datachar++ |= (fragment & 0x03c) >> 2;
*datachar = (fragment & 0x003) << 6;
case step_D:
do {
if (codechar == codeend)
{
state_in->step = step_D;
state_in->result = *datachar;
return datachar - data_out;
}
fragment = cbase64__decode_value(*codechar++);
} while (fragment < 0);
*datachar++ |= (fragment & 0x03f);
}
}
// control should not reach here
return datachar - data_out;
}
unsigned int cbase64_encode_blockend(char* code_out, cbase64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
*codechar++ = cbase64__encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = cbase64__encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
return codechar - code_out;
}
#endif // CBASE64_IMPLEMENTATION

View File

@ -1,33 +0,0 @@
libb64: Base64 Encoding/Decoding Routines
======================================
## Changelog ##
Version 1.2.1 Release
---------------------
Fixed a long-standing bug in src/cdecode.c where value_in was not correctly
checked against the bounds [0..decoding_size)
Thanks to both Mario Rugiero and Shlok Datye for pointing this out.
Added some simple example code to answer some of the most common misconceptions
people have about the library usage.
Version 1.2 Release
-------------------
Removed the b64dec, b64enc, encoder and decoder programs in favour of
a better example, called base64, which encodes and decodes
depending on its arguments.
Created a solution for Microsoft Visual Studio C++ Express 2010
edition, which simply builds the base64 example as a console application.
Version 1.1 Release
-------------------
Modified encode.h to (correctly) read from the iostream argument,
instead of std::cin.
Thanks to Peter K. Lee for the heads-up.
No API changes.
Version 1.0 Release
-------------------
The current content is the changeset.

View File

@ -1,29 +0,0 @@
/*
cdecode.h - c header for a base64 decoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CDECODE_H
#define BASE64_CDECODE_H
typedef enum
{
step_a, step_b, step_c, step_d
} base64_decodestep;
typedef struct
{
base64_decodestep step;
char plainchar;
} base64_decodestate;
void base64_init_decodestate(base64_decodestate* state_in);
int base64_decode_value(char value_in);
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
#endif /* BASE64_CDECODE_H */

View File

@ -1,38 +0,0 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
typedef enum
{
step_A, step_B, step_C
} base64_encodestep;
typedef enum
{
BASE64_ENC_NO_NEWLINE_TERM = 0x1
} base64_encodeflags;
typedef struct
{
base64_encodeflags flags;
base64_encodestep step;
int stepcount;
char result;
} base64_encodestate;
void base64_init_encodestate(base64_encodestate* state_in);
int base64_calc_buffer_length(int length_in, const base64_encodestate* state_in);
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#endif /* BASE64_CENCODE_H */

View File

@ -1,20 +0,0 @@
// :mode=c++:
/*
decode.h - c++ wrapper for a base64 decoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_DECODE_H
#define BASE64_DECODE_H
namespace base64
{
extern "C"
{
#include "cdecode.h"
}
} // namespace base64
#endif // BASE64_DECODE_H

View File

@ -1,20 +0,0 @@
// :mode=c++:
/*
encode.h - c++ wrapper for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_ENCODE_H
#define BASE64_ENCODE_H
namespace base64
{
extern "C"
{
#include "cencode.h"
}
} // namespace base64
#endif // BASE64_ENCODE_H

View File

@ -1,88 +0,0 @@
/*
cdecoder.c - c source to a base64 decoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/cdecode.h>
int base64_decode_value(char value_in)
{
static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static const char decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in >= decoding_size) return -1;
return decoding[(int)value_in];
}
void base64_init_decodestate(base64_decodestate* state_in)
{
state_in->step = step_a;
state_in->plainchar = 0;
}
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
{
const char* codechar = code_in;
char* plainchar = plaintext_out;
char fragment;
*plainchar = state_in->plainchar;
switch (state_in->step)
{
while (1)
{
case step_a:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_a;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar = (fragment & 0x03f) << 2;
case step_b:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_b;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x030) >> 4;
*plainchar = (fragment & 0x00f) << 4;
case step_c:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_c;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03c) >> 2;
*plainchar = (fragment & 0x003) << 6;
case step_d:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_d;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03f);
}
}
/* control should not reach here */
return plainchar - plaintext_out;
}

View File

@ -1,127 +0,0 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/cencode.h>
const int CHARS_PER_LINE = 72;
void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->flags = 0;
state_in->step = step_A;
state_in->stepcount = 0;
state_in->result = 0;
}
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}
/*
Output_size calculation from:
http://stackoverflow.com/questions/1533113/calculate-the-size-to-a-base-64-encoded-message
Never more than a byte larger than the actual encoded size.
Guaranteed equal to or larger than the actual encoded size.
*/
int base64_calc_buffer_length(int length_in, const base64_encodestate* state_in)
{
const int blockend_newline = ((BASE64_ENC_NO_NEWLINE_TERM & state_in->flags) == 0);
const int output_length = ((((length_in - 1) / 3) * 4) + 4);
return output_length + blockend_newline + (output_length / CHARS_PER_LINE);
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
int stepcount = state_in->stepcount;
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result = state_in->result;
char fragment;
switch (state_in->step)
{
while (1)
{
case step_A:
if (plainchar == plaintextend)
{
state_in->step = step_A;
state_in->stepcount = stepcount;
state_in->result = result;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (plainchar == plaintextend)
{
state_in->step = step_B;
state_in->stepcount = stepcount;
state_in->result = result;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (plainchar == plaintextend)
{
state_in->step = step_C;
state_in->stepcount = stepcount;
state_in->result = result;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
if (++stepcount == CHARS_PER_LINE/4)
{
*codechar++ = '\n';
stepcount = 0;
}
}
}
/* control should not reach here */
return codechar - code_out;
}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
if ((BASE64_ENC_NO_NEWLINE_TERM & state_in->flags) == 0)
{
*codechar++ = '\n';
}
return codechar - code_out;
}

View File

@ -29,7 +29,7 @@ solution "demboyz"
includedirs includedirs
{ {
"../external/json_checker/include", "../external/json_checker/include",
"../external/libb64-1.2.1/include", "../external/cbase64-1.0/include",
"../external/sourcesdk/include", "../external/sourcesdk/include",
"../external/rapidjson-1.0.2/include", "../external/rapidjson-1.0.2/include",
"../demboyz" "../demboyz"