/*
 * Copyright (c) 2012 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Andreas Hansson
 */

#include "proto/protoio.hh"

#include "base/logging.hh"

using namespace std;
using namespace google::protobuf;

ProtoOutputStream::ProtoOutputStream(const string& filename) :
    fileStream(filename.c_str(), ios::out | ios::binary | ios::trunc),
    wrappedFileStream(NULL), gzipStream(NULL), zeroCopyStream(NULL)
{
    if (!fileStream.good())
        panic("Could not open %s for writing\n", filename);

    // Wrap the output file in a zero copy stream, that in turn is
    // wrapped in a gzip stream if the filename ends with .gz. The
    // latter stream is in turn wrapped in a coded stream
    wrappedFileStream = new io::OstreamOutputStream(&fileStream);
    if (filename.find_last_of('.') != string::npos &&
        filename.substr(filename.find_last_of('.') + 1) == "gz") {
        gzipStream = new io::GzipOutputStream(wrappedFileStream);
        zeroCopyStream = gzipStream;
    } else {
        zeroCopyStream = wrappedFileStream;
    }

    // Write the magic number to the file
    io::CodedOutputStream codedStream(zeroCopyStream);
    codedStream.WriteLittleEndian32(magicNumber);

    // Note that each type of stream (packet, instruction etc) should
    // add its own header and perform the appropriate checks
}

ProtoOutputStream::~ProtoOutputStream()
{
    // As the compression is optional, see if the stream exists
    if (gzipStream != NULL)
        delete gzipStream;
    delete wrappedFileStream;
    fileStream.close();
}

void
ProtoOutputStream::write(const Message& msg)
{
    // Due to the byte limit of the coded stream we create it for
    // every single mesage (based on forum discussions around the size
    // limitation)
    io::CodedOutputStream codedStream(zeroCopyStream);

    // Write the size of the message to the stream
    codedStream.WriteVarint32(msg.ByteSize());

    // Write the message itself to the stream
    msg.SerializeWithCachedSizes(&codedStream);
}

ProtoInputStream::ProtoInputStream(const string& filename) :
    fileStream(filename.c_str(), ios::in | ios::binary), fileName(filename),
    useGzip(false),
    wrappedFileStream(NULL), gzipStream(NULL), zeroCopyStream(NULL)
{
    if (!fileStream.good())
        panic("Could not open %s for reading\n", filename);

    // check the magic number to see if this is a gzip stream
    unsigned char bytes[2];
    fileStream.read((char*) bytes, 2);
    useGzip = fileStream.good() && bytes[0] == 0x1f && bytes[1] == 0x8b;

    // seek to the start of the input file and clear any flags
    fileStream.clear();
    fileStream.seekg(0, ifstream::beg);

    createStreams();
}

void
ProtoInputStream::createStreams()
{
    // All streams should be NULL at this point
    assert(wrappedFileStream == NULL && gzipStream == NULL &&
           zeroCopyStream == NULL);

    // Wrap the input file in a zero copy stream, that in turn is
    // wrapped in a gzip stream if the filename ends with .gz. The
    // latter stream is in turn wrapped in a coded stream
    wrappedFileStream = new io::IstreamInputStream(&fileStream);
    if (useGzip) {
        gzipStream = new io::GzipInputStream(wrappedFileStream);
        zeroCopyStream = gzipStream;
    } else {
        zeroCopyStream = wrappedFileStream;
    }

    uint32_t magic_check;
    io::CodedInputStream codedStream(zeroCopyStream);
    if (!codedStream.ReadLittleEndian32(&magic_check) ||
        magic_check != magicNumber)
        panic("Input file %s is not a valid gem5 proto format.\n",
              fileName);
}

void
ProtoInputStream::destroyStreams()
{
    // As the compression is optional, see if the stream exists
    if (gzipStream != NULL) {
        delete gzipStream;
        gzipStream = NULL;
    }
    delete wrappedFileStream;
    wrappedFileStream = NULL;

    zeroCopyStream = NULL;
}


ProtoInputStream::~ProtoInputStream()
{
    destroyStreams();
    fileStream.close();
}


void
ProtoInputStream::reset()
{
    destroyStreams();
    // seek to the start of the input file and clear any flags
    fileStream.clear();
    fileStream.seekg(0, ifstream::beg);
    createStreams();
}

bool
ProtoInputStream::read(Message& msg)
{
    // Read a message from the stream by getting the size, using it as
    // a limit when parsing the message, then popping the limit again
    uint32_t size;

    // Due to the byte limit of the coded stream we create it for
    // every single mesage (based on forum discussions around the size
    // limitation)
    io::CodedInputStream codedStream(zeroCopyStream);
    if (codedStream.ReadVarint32(&size)) {
        io::CodedInputStream::Limit limit = codedStream.PushLimit(size);
        if (msg.ParseFromCodedStream(&codedStream)) {
            codedStream.PopLimit(limit);
            // All went well, the message is parsed and the limit is
            // popped again
            return true;
        } else {
            panic("Unable to read message from coded stream %s\n",
                  fileName);
        }
    }

    return false;
}
