//
// tardy - a tar post-processor
// Copyright (C) 2011 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 <http://www.gnu.org/licenses/>.
//

#include <libtardy/ac/stdio.h>
#include <libtardy/ac/string.h>

#include <libtardy/tar/output/ar.h>


tar_output_ar::~tar_output_ar()
{
}


tar_output_ar::tar_output_ar(const file_output::pointer &a_ofp, int a_padding) :
    ofp(a_ofp),
    padding(a_padding >= 2 ? a_padding : 0),
    position(0)
{
    assert(ofp);
}


void
tar_output_ar::write_header_padding(void)
{
    write_padding();
}


void
tar_output_ar::write_data(const void *data, int data_size)
{
    assert(data_size >= 0);
    write_deeper(data, data_size);
}


void
tar_output_ar::write_data_padding(void)
{
    write_padding();
}


void
tar_output_ar::write_deeper(const void *data, size_t data_size)
{
    ofp->write(data, data_size);
    position += data_size;
}


rcstring
tar_output_ar::filename(void)
    const
{
    return ofp->filename();
}


void
tar_output_ar::write_padding(void)
{
    if (!padding)
        return;
    unsigned mod = position % padding;
    if (!mod)
        return;
    unsigned pad = padding - mod;
    static char *dummy;
    static size_t dummy_size;
    if (dummy_size < pad)
    {
        delete [] dummy;
        dummy_size = padding;
        dummy = new char [dummy_size];
        memset(dummy, '\n', dummy_size);
    }
    write_deeper(dummy, pad);
}


void
tar_output_ar::dec(char *data, unsigned long value, size_t data_size)
{
    char temp[60];
    snprintf(temp, sizeof(temp), "%lu", value);
    size_t temp_len = strlen(temp);
    if (temp_len > data_size)
    {
        memset(data, '9', data_size);
        return;
    }
    memcpy(data, temp, temp_len);
    memset(data + temp_len, ' ', data_size - temp_len);
}


void
tar_output_ar::oct(char *data, unsigned long value, size_t data_size)
{
    char temp[60];
    snprintf(temp, sizeof(temp), "%lo", value);
    size_t temp_len = strlen(temp);
    if (temp_len > data_size)
    {
        memset(data, '7', data_size);
        return;
    }
    memcpy(data, temp, temp_len);
    memset(data + temp_len, ' ', data_size - temp_len);
}
