Workshop o mikrokontrolérech na SKSP 2024.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
2.9 KiB

3 months ago
/*
* UCW Library -- Line utility for encoding and decoding base64 & base224
*
* (c) 2008, Michal Vaner <vorner@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucw/lib.h>
#include <ucw/base64.h>
#include <ucw/base224.h>
#include <ucw/fastbuf.h>
#include <ucw/getopt.h>
static struct option opts[] = {
{ "encode64", 0, 0, 'e' },
{ "decode64", 0, 0, 'd' },
{ "encode224", 0, 0, 'E' },
{ "decode224", 0, 0, 'D' },
{ "prefix", 1, 0, 'p' },
{ "blocks", 1, 0, 'b' },
{ 0, 0, 0, 0 }
};
static const struct {
uint (*function)(byte *, const byte *, uint);
uint in_block, out_block, num_blocks;
uint add_prefix;
} actions[] = {
{
base64_encode,
BASE64_IN_CHUNK, BASE64_OUT_CHUNK, 20,
1
},
{
base64_decode,
BASE64_OUT_CHUNK, BASE64_IN_CHUNK, 20,
0
},
{
base224_encode,
BASE224_IN_CHUNK, BASE64_OUT_CHUNK, 6,
1
},
{
base224_decode,
BASE224_OUT_CHUNK, BASE224_IN_CHUNK, 6,
0
}
};
int main(int argc, char **argv)
{
// Choose mode
int mode = -1;
char *prefix = NULL;
uint blocks = 0;
int opt;
while ((opt = getopt_long(argc, argv, "edEDp:b:", opts, NULL)) >= 0)
switch (opt)
{
case 'e': mode = 0; break;
case 'd': mode = 1; break;
case 'E': mode = 2; break;
case 'D': mode = 3; break;
case 'p': prefix = optarg; break;
case 'b':
{
char *end;
blocks = strtol(optarg, &end, 0);
if ((blocks > 0) && !*end)
break;
}
default: goto usage;
}
if (mode == -1)
{
usage:
fprintf(stderr, "ucw-basecode mode [--prefix=prefix] [--blocks=number_of_blocks]\nMode is one of:\n\t--encode64 (-e)\n\t--decode64 (-d)\n\t--encode224 (-E)\n\t--decode224 (-D)\n");
return 1;
}
if (!blocks)
blocks = actions[mode].num_blocks;
// Prepare buffers
struct fastbuf *in = bfdopen_shared(0, 4096);
struct fastbuf *out = bfdopen_shared(1, 4096);
int has_offset = !actions[mode].add_prefix && prefix;
uint offset = has_offset ? strlen(prefix) : 0;
uint read_size = actions[mode].in_block * blocks + offset + has_offset;
uint write_size = actions[mode].out_block * blocks;
byte in_buff[read_size], out_buff[write_size];
uint isize;
// Recode it
while (isize = bread(in, in_buff, read_size))
{
if (prefix)
{
if (actions[mode].add_prefix)
bputs(out, prefix);
else
if ((isize < offset) || (in_buff[isize-1] != '\n')
|| (strncmp(prefix, in_buff, offset)))
die("Invalid line syntax");
}
uint osize = actions[mode].function(out_buff, in_buff + offset, isize - offset - has_offset);
bwrite(out, out_buff, osize);
if (actions[mode].add_prefix && prefix)
bputc(out, '\n');
}
bclose(in);
bclose(out);
return 0;
}