Initial import.

This commit is contained in:
Thomas Pornin 2016-11-02 19:01:13 -04:00
commit 3210f38e04
292 changed files with 58526 additions and 0 deletions

44
src/codec/ccopy.c Normal file
View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len)
{
unsigned char *d;
const unsigned char *s;
d = dst;
s = src;
while (len -- > 0) {
uint32_t x, y;
x = *s ++;
y = *d;
*d = MUX(ctl, x, y);
d ++;
}
}

38
src/codec/dec16be.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_dec16be(uint16_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = src;
while (num -- > 0) {
*v ++ = br_dec16be(buf);
buf += 2;
}
}

38
src/codec/dec16le.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_dec16le(uint16_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = src;
while (num -- > 0) {
*v ++ = br_dec16le(buf);
buf += 2;
}
}

38
src/codec/dec32be.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_dec32be(uint32_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = src;
while (num -- > 0) {
*v ++ = br_dec32be(buf);
buf += 4;
}
}

38
src/codec/dec32le.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_dec32le(uint32_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = src;
while (num -- > 0) {
*v ++ = br_dec32le(buf);
buf += 4;
}
}

38
src/codec/dec64be.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_dec64be(uint64_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = src;
while (num -- > 0) {
*v ++ = br_dec64be(buf);
buf += 8;
}
}

38
src/codec/dec64le.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_dec64le(uint64_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = src;
while (num -- > 0) {
*v ++ = br_dec64le(buf);
buf += 8;
}
}

38
src/codec/enc16be.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_enc16be(void *dst, const uint16_t *v, size_t num)
{
unsigned char *buf;
buf = dst;
while (num -- > 0) {
br_enc16be(buf, *v ++);
buf += 2;
}
}

38
src/codec/enc16le.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_enc16le(void *dst, const uint16_t *v, size_t num)
{
unsigned char *buf;
buf = dst;
while (num -- > 0) {
br_enc16le(buf, *v ++);
buf += 2;
}
}

38
src/codec/enc32be.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_enc32be(void *dst, const uint32_t *v, size_t num)
{
unsigned char *buf;
buf = dst;
while (num -- > 0) {
br_enc32be(buf, *v ++);
buf += 4;
}
}

38
src/codec/enc32le.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_enc32le(void *dst, const uint32_t *v, size_t num)
{
unsigned char *buf;
buf = dst;
while (num -- > 0) {
br_enc32le(buf, *v ++);
buf += 4;
}
}

38
src/codec/enc64be.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_enc64be(void *dst, const uint64_t *v, size_t num)
{
unsigned char *buf;
buf = dst;
while (num -- > 0) {
br_enc64be(buf, *v ++);
buf += 8;
}
}

38
src/codec/enc64le.c Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see inner.h */
void
br_range_enc64le(void *dst, const uint64_t *v, size_t num)
{
unsigned char *buf;
buf = dst;
while (num -- > 0) {
br_enc64le(buf, *v ++);
buf += 8;
}
}

508
src/codec/pemdec.c Normal file
View file

@ -0,0 +1,508 @@
/* Automatically generated code; do not modify directly. */
#include <stddef.h>
#include <stdint.h>
typedef struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} t0_context;
static uint32_t
t0_parse7E_unsigned(const unsigned char **p)
{
uint32_t x;
x = 0;
for (;;) {
unsigned y;
y = *(*p) ++;
x = (x << 7) | (uint32_t)(y & 0x7F);
if (y < 0x80) {
return x;
}
}
}
static int32_t
t0_parse7E_signed(const unsigned char **p)
{
int neg;
uint32_t x;
neg = ((**p) >> 6) & 1;
x = (uint32_t)-neg;
for (;;) {
unsigned y;
y = *(*p) ++;
x = (x << 7) | (uint32_t)(y & 0x7F);
if (y < 0x80) {
if (neg) {
return -(int32_t)~x - 1;
} else {
return (int32_t)x;
}
}
}
}
#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
#define T0_INT1(x) T0_FBYTE(x, 0)
#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
static const uint8_t t0_datablock[];
void br_pem_decoder_init_main(void *t0ctx);
void br_pem_decoder_run(void *t0ctx);
#include "inner.h"
#define CTX ((br_pem_decoder_context *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
/* see bearssl_pem.h */
void
br_pem_decoder_init(br_pem_decoder_context *ctx)
{
memset(ctx, 0, sizeof *ctx);
ctx->cpu.dp = &ctx->dp_stack[0];
ctx->cpu.rp = &ctx->rp_stack[0];
br_pem_decoder_init_main(&ctx->cpu);
br_pem_decoder_run(&ctx->cpu);
}
/* see bearssl_pem.h */
size_t
br_pem_decoder_push(br_pem_decoder_context *ctx,
const void *data, size_t len)
{
if (ctx->event) {
return 0;
}
ctx->hbuf = data;
ctx->hlen = len;
br_pem_decoder_run(&ctx->cpu);
return len - ctx->hlen;
}
/* see bearssl_pem.h */
int
br_pem_decoder_event(br_pem_decoder_context *ctx)
{
int event;
event = ctx->event;
ctx->event = 0;
return event;
}
static const uint8_t t0_datablock[] = {
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20,
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00
};
static const uint8_t t0_codeblock[] = {
0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01,
0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01,
T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01,
T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05,
0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01,
0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27,
0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00,
0x01, 0x01, 0x7F, 0x03, 0x00, 0x24, 0x01, 0x00, 0x17, 0x0D, 0x06, 0x03,
0x13, 0x04, 0x3C, 0x01, 0x7F, 0x17, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00,
0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x22, 0x01,
0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x17, 0x0D, 0x06, 0x09, 0x13, 0x01,
0x00, 0x22, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x17, 0x0D, 0x06,
0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01,
0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C,
0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31,
0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01,
0x02, 0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00,
0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03,
0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02,
0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D,
0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E,
0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00,
0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03,
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03,
0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1B, 0x01, 0x01, 0x00, 0x25, 0x14,
0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06,
0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13,
0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05,
0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01,
0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1B, 0x02, 0x00, 0x01, 0x02,
0x0F, 0x1B, 0x01, 0x01, 0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E,
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02,
0x00, 0x01, 0x10, 0x0F, 0x1B, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1B, 0x02,
0x00, 0x1B, 0x01, 0x00, 0x00, 0x00, 0x14, 0x14, 0x01, 0x80, 0x41, 0x0E,
0x1A, 0x01, 0x80, 0x5A, 0x0B, 0x10, 0x06, 0x05, 0x01, 0x80, 0x41, 0x08,
0x00, 0x14, 0x14, 0x01, 0x80, 0x61, 0x0E, 0x1A, 0x01, 0x80, 0x7A, 0x0B,
0x10, 0x06, 0x05, 0x01, 0x80, 0x47, 0x08, 0x00, 0x14, 0x14, 0x01, 0x30,
0x0E, 0x1A, 0x01, 0x39, 0x0B, 0x10, 0x06, 0x04, 0x01, 0x04, 0x07, 0x00,
0x14, 0x01, 0x2B, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x3E, 0x00, 0x14, 0x01,
0x2F, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x3F, 0x00, 0x01, 0x3D, 0x0C, 0x1E,
0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x23, 0x06, 0x02, 0x04, 0x7B, 0x04,
0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04, 0x1F, 0x01, 0x7F, 0x00,
0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05, 0x13, 0x1F, 0x01, 0x00,
0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00, 0x00, 0x1D, 0x04, 0x5E,
0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x21, 0x01, 0x80, 0x7F, 0x2B, 0x14,
0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00, 0x2C, 0x14, 0x31, 0x05,
0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14, 0x01, 0x80, 0x61, 0x0E,
0x1A, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03, 0x01, 0x20, 0x08, 0x00,
0x01, 0x14, 0x03, 0x00, 0x1A, 0x17, 0x05, 0x05, 0x1F, 0x2E, 0x01, 0x00,
0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06, 0x1F, 0x02, 0x00, 0x1A,
0x08, 0x00, 0x2A, 0x17, 0x19, 0x1D, 0x1A, 0x1E, 0x1A, 0x04, 0x62, 0x00,
0x18, 0x14, 0x1C, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00, 0x20,
0x19, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04, 0x78,
0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C, 0x06,
0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13, 0x02,
0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1E, 0x14, 0x21, 0x07, 0x16, 0x01,
0x2D, 0x0C, 0x06, 0x08, 0x21, 0x07, 0x1D, 0x01, 0x00, 0x1A, 0x19, 0x00,
0x04, 0x69, 0x21, 0x19, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1A, 0x01,
0x20, 0x0B, 0x10, 0x00
};
static const uint16_t t0_caddr[] = {
0,
5,
10,
15,
19,
24,
29,
67,
149,
384,
464,
476,
511,
530,
540,
559,
594,
605,
610,
620,
645,
672
};
#define T0_INTERPRETED 28
#define T0_ENTER(ip, rp, slot) do { \
const unsigned char *t0_newip; \
uint32_t t0_lnum; \
t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
t0_lnum = t0_parse7E_unsigned(&t0_newip); \
(rp) += t0_lnum; \
*((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
(ip) = t0_newip; \
} while (0)
#define T0_DEFENTRY(name, slot) \
void \
name(void *ctx) \
{ \
t0_context *t0ctx = ctx; \
t0ctx->ip = &t0_codeblock[0]; \
T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
}
T0_DEFENTRY(br_pem_decoder_init_main, 38)
void
br_pem_decoder_run(void *t0ctx)
{
uint32_t *dp, *rp;
const unsigned char *ip;
#define T0_LOCAL(x) (*(rp - 2 - (x)))
#define T0_POP() (*-- dp)
#define T0_POPi() (*(int32_t *)(-- dp))
#define T0_PEEK(x) (*(dp - 1 - (x)))
#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
#define T0_RPOP() (*-- rp)
#define T0_RPOPi() (*(int32_t *)(-- rp))
#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
#define T0_ROLL(x) do { \
size_t t0len = (size_t)(x); \
uint32_t t0tmp = *(dp - 1 - t0len); \
memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
*(dp - 1) = t0tmp; \
} while (0)
#define T0_SWAP() do { \
uint32_t t0tmp = *(dp - 2); \
*(dp - 2) = *(dp - 1); \
*(dp - 1) = t0tmp; \
} while (0)
#define T0_ROT() do { \
uint32_t t0tmp = *(dp - 3); \
*(dp - 3) = *(dp - 2); \
*(dp - 2) = *(dp - 1); \
*(dp - 1) = t0tmp; \
} while (0)
#define T0_NROT() do { \
uint32_t t0tmp = *(dp - 1); \
*(dp - 1) = *(dp - 2); \
*(dp - 2) = *(dp - 3); \
*(dp - 3) = t0tmp; \
} while (0)
#define T0_PICK(x) do { \
uint32_t t0depth = (x); \
T0_PUSH(T0_PEEK(t0depth)); \
} while (0)
#define T0_CO() do { \
goto t0_exit; \
} while (0)
#define T0_RET() break
dp = ((t0_context *)t0ctx)->dp;
rp = ((t0_context *)t0ctx)->rp;
ip = ((t0_context *)t0ctx)->ip;
for (;;) {
uint32_t t0x;
t0x = t0_parse7E_unsigned(&ip);
if (t0x < T0_INTERPRETED) {
switch (t0x) {
int32_t t0off;
case 0: /* ret */
t0x = T0_RPOP();
rp -= (t0x >> 16);
t0x &= 0xFFFF;
if (t0x == 0) {
ip = NULL;
goto t0_exit;
}
ip = &t0_codeblock[t0x];
break;
case 1: /* literal constant */
T0_PUSHi(t0_parse7E_signed(&ip));
break;
case 2: /* read local */
T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
break;
case 3: /* write local */
T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
break;
case 4: /* jump */
t0off = t0_parse7E_signed(&ip);
ip += t0off;
break;
case 5: /* jump if */
t0off = t0_parse7E_signed(&ip);
if (T0_POP()) {
ip += t0off;
}
break;
case 6: /* jump if not */
t0off = t0_parse7E_signed(&ip);
if (!T0_POP()) {
ip += t0off;
}
break;
case 7: {
/* + */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(a + b);
}
break;
case 8: {
/* - */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(a - b);
}
break;
case 9: {
/* < */
int32_t b = T0_POPi();
int32_t a = T0_POPi();
T0_PUSH(-(uint32_t)(a < b));
}
break;
case 10: {
/* << */
int c = (int)T0_POPi();
uint32_t x = T0_POP();
T0_PUSH(x << c);
}
break;
case 11: {
/* <= */
int32_t b = T0_POPi();
int32_t a = T0_POPi();
T0_PUSH(-(uint32_t)(a <= b));
}
break;
case 12: {
/* <> */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(-(uint32_t)(a != b));
}
break;
case 13: {
/* = */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(-(uint32_t)(a == b));
}
break;
case 14: {
/* >= */
int32_t b = T0_POPi();
int32_t a = T0_POPi();
T0_PUSH(-(uint32_t)(a >= b));
}
break;
case 15: {
/* >> */
int c = (int)T0_POPi();
int32_t x = T0_POPi();
T0_PUSHi(x >> c);
}
break;
case 16: {
/* and */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(a & b);
}
break;
case 17: {
/* co */
T0_CO();
}
break;
case 18: {
/* data-get8 */
size_t addr = T0_POP();
T0_PUSH(t0_datablock[addr]);
}
break;
case 19: {
/* drop */
(void)T0_POP();
}
break;
case 20: {
/* dup */
T0_PUSH(T0_PEEK(0));
}
break;
case 21: {
/* flush-buf */
if (CTX->ptr > 0) {
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
CTX->ptr = 0;
}
}
break;
case 22: {
/* get8 */
size_t addr = T0_POP();
T0_PUSH(*((unsigned char *)CTX + addr));
}
break;
case 23: {
/* over */
T0_PUSH(T0_PEEK(1));
}
break;
case 24: {
/* read8-native */
if (CTX->hlen > 0) {
T0_PUSH(*CTX->hbuf ++);
CTX->hlen --;
} else {
T0_PUSHi(-1);
}
}
break;
case 25: {
/* set8 */
size_t addr = T0_POP();
unsigned x = T0_POP();
*((unsigned char *)CTX + addr) = x;
}
break;
case 26: {
/* swap */
T0_SWAP();
}
break;
case 27: {
/* write8 */
unsigned char x = (unsigned char)T0_POP();
CTX->buf[CTX->ptr ++] = x;
if (CTX->ptr == sizeof CTX->buf) {
if (CTX->dest) {
CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
}
CTX->ptr = 0;
}
}
break;
}
} else {
T0_ENTER(ip, rp, t0x);
}
}
t0_exit:
((t0_context *)t0ctx)->dp = dp;
((t0_context *)t0ctx)->rp = rp;
((t0_context *)t0ctx)->ip = ip;
}

303
src/codec/pemdec.t0 Normal file
View file

@ -0,0 +1,303 @@
\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
\
\ Permission is hereby granted, free of charge, to any person obtaining
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\ SOFTWARE.
preamble {
#include "inner.h"
#define CTX ((br_pem_decoder_context *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
/* see bearssl_pem.h */
void
br_pem_decoder_init(br_pem_decoder_context *ctx)
{
memset(ctx, 0, sizeof *ctx);
ctx->cpu.dp = &ctx->dp_stack[0];
ctx->cpu.rp = &ctx->rp_stack[0];
br_pem_decoder_init_main(&ctx->cpu);
br_pem_decoder_run(&ctx->cpu);
}
/* see bearssl_pem.h */
size_t
br_pem_decoder_push(br_pem_decoder_context *ctx,
const void *data, size_t len)
{
if (ctx->event) {
return 0;
}
ctx->hbuf = data;
ctx->hlen = len;
br_pem_decoder_run(&ctx->cpu);
return len - ctx->hlen;
}
/* see bearssl_pem.h */
int
br_pem_decoder_event(br_pem_decoder_context *ctx)
{
int event;
event = ctx->event;
ctx->event = 0;
return event;
}
}
\ Define a word that evaluates to the address of a field within the
\ decoder context.
: addr:
next-word { field }
"addr-" field + 0 1 define-word
0 8191 "offsetof(br_pem_decoder_context, " field + ")" + make-CX
postpone literal postpone ; ;
addr: event
addr: name
addr: buf
addr: ptr
\ Set a byte at a specific address (offset within the context).
cc: set8 ( value addr -- ) {
size_t addr = T0_POP();
unsigned x = T0_POP();
*((unsigned char *)CTX + addr) = x;
}
\ Get a byte at a specific address (offset within the context).
cc: get8 ( addr -- value ) {
size_t addr = T0_POP();
T0_PUSH(*((unsigned char *)CTX + addr));
}
\ Send an event.
: send-event ( event -- )
addr-event set8 co ;
\ Low-level function to read a single byte. Returned value is the byte
\ (0 to 255), or -1 if there is no available data.
cc: read8-native ( -- x ) {
if (CTX->hlen > 0) {
T0_PUSH(*CTX->hbuf ++);
CTX->hlen --;
} else {
T0_PUSHi(-1);
}
}
\ Read next byte. Block until the next byte is available.
: read8 ( -- x )
begin read8-native dup 0< ifnot ret then drop co again ;
\ Read bytes until next end-of-line.
: skip-newline ( -- )
begin read8 `\n <> while repeat ;
\ Read bytes until next end-of-line; verify that they are all whitespace.
\ This returns -1 if they were all whitespace, 0 otherwise.
: skip-newline-ws ( -- bool )
-1 { r }
begin read8 dup `\n <> while ws? ifnot 0 >r then repeat
drop r ;
\ Normalise a byte to uppercase (ASCII only).
: norm-upper ( x -- x )
dup dup `a >= swap `z <= and if 32 - then ;
\ Read bytes and compare with the provided string. On mismatch, the
\ rest of the line is consumed. Matching is not case sensitive.
: match-string ( str -- bool )
begin
dup data-get8 norm-upper dup ifnot 2drop -1 ret then
read8 norm-upper dup `\n = if drop 2drop 0 ret then
= ifnot drop skip-newline 0 ret then
1+
again ;
\ Read bytes into the provided buffer, but no more than the provided
\ count. Reading stops when end-of-line is reached. Returned value
\ is the count of bytes written to the buffer, or 0 if the buffer size
\ was exceeded. All bytes are normalised to uppercase (ASCII only).
: read-bytes ( addr len -- len )
dup { orig-len }
swap
begin
over ifnot 2drop skip-newline 0 ret then
read8 dup `\n = if 2drop orig-len swap - ret then
norm-upper over set8 1+ swap 1- swap
again ;
\ Remove trailing dashes from the name buffer.
: trim-dashes ( len -- )
begin dup while
1-
dup addr-name + get8 `- <> if
addr-name + 1+ 0 swap set8 ret
then
repeat
addr-name set8 ;
\ Scan input for next "begin" banner.
: next-banner-begin ( -- )
begin
"-----BEGIN " match-string if
addr-name 127 read-bytes
dup if trim-dashes ret then
drop
then
again ;
\ Convert a Base64 character to its numerical value. Returned value is
\ 0 to 63 for Base64 characters, -1 for '=', and -2 for all other characters.
: from-base64 ( char -- x )
dup dup `A >= swap `Z <= and if 65 - ret then
dup dup `a >= swap `z <= and if 71 - ret then
dup dup `0 >= swap `9 <= and if 4 + ret then
dup `+ = if drop 62 ret then
dup `/ = if drop 63 ret then
`= <> 1- ;
\ Test whether a character is whitespace (but not a newline).
: ws? ( x -- bool )
dup `\n <> swap 32 <= and ;
\ Read next character, skipping whitespace (except newline).
: next-nonws ( -- x )
begin
read8 dup ws? ifnot ret then
drop
again ;
\ Write one byte in the output buffer.
cc: write8 ( x -- ) {
unsigned char x = (unsigned char)T0_POP();
CTX->buf[CTX->ptr ++] = x;
if (CTX->ptr == sizeof CTX->buf) {
if (CTX->dest) {
CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
}
CTX->ptr = 0;
}
}
\ Flush the output buffer.
cc: flush-buf ( -- ) {
if (CTX->ptr > 0) {
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
CTX->ptr = 0;
}
}
\ Decode the four next Base64 characters. Returned value is:
\ 0 quartet processed, three bytes produced.
\ -1 dash encountered as first character (no leading whitespace).
\ 1 quartet processed, one or two bytes produced, terminator reached.
\ 2 end-of-line reached.
\ 3 error.
\ For all positive return values, the remaining of the current line has been
\ consumed.
: decode-next-quartet ( -- r )
\ Process first character. It may be a dash.
read8 dup `- = if drop -1 ret then
dup ws? if drop next-nonws then
dup `\n = if drop 2 ret then
from-base64 dup 0< if drop skip-newline 3 ret then
{ acc }
\ Second character.
next-nonws dup `\n = if drop 3 ret then
from-base64 dup 0< if drop skip-newline 3 ret then
acc 6 << + >acc
\ Third character: may be an equal sign.
next-nonws dup `\n = if drop 3 ret then
dup `= = if
\ Fourth character must be an equal sign.
drop
next-nonws dup `\n = if drop 3 ret then
skip-newline-ws ifnot drop 3 ret then
`= <> if 3 ret then
acc 0x0F and if 3 ret then
acc 4 >> write8
1 ret
then
from-base64 dup 0< if drop skip-newline 3 ret then
acc 6 << + >acc
\ Fourth character: may be an equal sign.
next-nonws dup `\n = if drop 3 ret then
dup `= = if
drop skip-newline-ws ifnot 3 ret then
acc 0x03 and if 3 ret then
acc 10 >> write8
acc 2 >> write8
1 ret
then
from-base64 dup 0< if drop skip-newline 3 ret then
acc 6 << + >acc
acc 16 >> write8
acc 8 >> write8
acc write8
0 ;
\ Check trailer line (possibly, the leading dash has been read). This
\ sends the appropriate event.
: check-trailer ( bool -- )
ifnot
begin read8 dup `\n = while drop repeat
`- <> if skip-newline 3 send-event ret then
then
"----END " match-string ifnot 3 send-event ret then
flush-buf
skip-newline 2 send-event ;
\ Decode one line worth of characters. Returned value is 0 if the end of the
\ object is reached, -1 otherwise. The end of object or error event is sent.
: decode-line ( -- bool )
-1 { first }
begin
decode-next-quartet
case
0 of endof
-1 of
first ifnot
skip-newline 3 send-event
else
-1 check-trailer
then
0 ret
endof
1 of 0 check-trailer 0 ret endof
2 of -1 ret endof
\ On decoding error
drop 3 send-event 0 ret
endcase
0 >first
again ;
: main ( -- ! )
begin
next-banner-begin 1 send-event
begin decode-line while repeat
again ;