//
// aegis - project change supervisor
// Copyright (C) 2014 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see .
//
#include
#include
#include
output_filter_base85::~output_filter_base85()
{
flush();
while (accumulator_nbytes)
encode(0);
if (column > 0)
deeper_fputc('\n');
char buf[80];
snprintf
(
buf,
sizeof(buf),
"xbtoa End N %lu %lx E %lx S %lx R %lx\n",
content_length,
content_length,
check_xor,
check_sum,
check_rot
);
deeper_fputs(buf);
}
output_filter_base85::output_filter_base85(
const pointer &a_deeper
) :
output_filter(a_deeper),
accumulator(0),
accumulator_nbytes(0),
column(0),
content_length(0),
check_xor(0),
check_sum(0),
check_rot(0),
bol(false)
{
deeper_fputs("xbtoa Begin\n");
}
output::pointer
output_filter_base85::create(const pointer &a_deeper)
{
return pointer(new output_filter_base85(a_deeper));
}
#define MAXPERLINE 78
void
output_filter_base85::char_out(unsigned char c)
{
deeper_fputc(c);
++column;
if (column >= MAXPERLINE)
{
deeper_fputc('\n');
column = 0;
}
}
void
output_filter_base85::word_out(unsigned long word)
{
if (word == 0)
{
char_out('z');
}
#if 0
else if (word == 0x20202020)
{
// If we are being conservative, we should not use this code,
// because the very first btoa(1) did not use it.
char_out('y');
}
#endif
else
{
unsigned char c5 = word % 85;
word /= 85;
unsigned char c4 = word % 85;
word /= 85;
unsigned char c3 = word % 85;
word /= 85;
unsigned char c2 = word % 85;
word /= 85;
assert(word < 83);
unsigned char c1 = word;
char_out('!' + c1);
char_out('!' + c2);
char_out('!' + c3);
char_out('!' + c4);
char_out('!' + c5);
}
}
void
output_filter_base85::encode(unsigned char c)
{
check_xor ^= c;
check_sum += c + 1;
check_rot = (check_rot << 1) | ((check_rot >> 31) & 1);
check_rot = (check_rot + c) & 0xFFFFFFFF;
accumulator |= c << ((3 - accumulator_nbytes) * 8);
++accumulator_nbytes;
if (accumulator_nbytes >= 4)
{
word_out(accumulator);
accumulator = 0;
accumulator_nbytes = 0;
}
}
void
output_filter_base85::write_inner(const void *data, size_t size)
{
const char *start = (const char *)data;
const char *end = start + size;
const char *cp = start;
content_length += size;
while (cp < end)
{
unsigned char c = *cp++;
encode(c);
bol = (c == '\n');
}
}
nstring
output_filter_base85::type_name(void)
const
{
return ("base64 " + output_filter::type_name());
}
void
output_filter_base85::end_of_line_inner(void)
{
if (column > 0)
{
write_inner("\n", 1);
}
}
long
output_filter_base85::ftell_inner(void)
const
{
return content_length;
}
// vim: set ts=8 sw=4 et :