protoio.cc revision 9464
19397Sandreas.hansson@arm.com/*
29397Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited
39397Sandreas.hansson@arm.com * All rights reserved
49397Sandreas.hansson@arm.com *
59397Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69397Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79397Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89397Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99397Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109397Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119397Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129397Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139397Sandreas.hansson@arm.com *
149397Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
159397Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
169397Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
179397Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
189397Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
199397Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
209397Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
219397Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
229397Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
239397Sandreas.hansson@arm.com * this software without specific prior written permission.
249397Sandreas.hansson@arm.com *
259397Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269397Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279397Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289397Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299397Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309397Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319397Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329397Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339397Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349397Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359397Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369397Sandreas.hansson@arm.com *
379397Sandreas.hansson@arm.com * Authors: Andreas Hansson
389397Sandreas.hansson@arm.com */
399397Sandreas.hansson@arm.com
409397Sandreas.hansson@arm.com#include "base/misc.hh"
419397Sandreas.hansson@arm.com#include "proto/protoio.hh"
429397Sandreas.hansson@arm.com
439397Sandreas.hansson@arm.comusing namespace std;
449397Sandreas.hansson@arm.comusing namespace google::protobuf;
459397Sandreas.hansson@arm.com
469397Sandreas.hansson@arm.comProtoOutputStream::ProtoOutputStream(const string& filename) :
479397Sandreas.hansson@arm.com    fileStream(filename.c_str(), ios::out | ios::binary | ios::trunc),
489397Sandreas.hansson@arm.com    zeroCopyStream(NULL), gzipStream(NULL), codedStream(NULL)
499397Sandreas.hansson@arm.com{
509397Sandreas.hansson@arm.com    if (!fileStream.good())
519397Sandreas.hansson@arm.com        panic("Could not open %s for writing\n", filename);
529397Sandreas.hansson@arm.com
539397Sandreas.hansson@arm.com    // Wrap the output file in a zero copy stream, that in turn is
549397Sandreas.hansson@arm.com    // wrapped in a gzip stream if the filename ends with .gz. The
559397Sandreas.hansson@arm.com    // latter stream is in turn wrapped in a coded stream
569397Sandreas.hansson@arm.com    zeroCopyStream = new io::OstreamOutputStream(&fileStream);
579397Sandreas.hansson@arm.com    if (filename.find_last_of('.') != string::npos &&
589397Sandreas.hansson@arm.com        filename.substr(filename.find_last_of('.') + 1) == "gz") {
599397Sandreas.hansson@arm.com        gzipStream = new io::GzipOutputStream(zeroCopyStream);
609397Sandreas.hansson@arm.com        codedStream = new io::CodedOutputStream(gzipStream);
619397Sandreas.hansson@arm.com    } else {
629397Sandreas.hansson@arm.com        codedStream = new io::CodedOutputStream(zeroCopyStream);
639397Sandreas.hansson@arm.com    }
649397Sandreas.hansson@arm.com
659399Sandreas.hansson@arm.com    // Write the magic number to the file
669399Sandreas.hansson@arm.com    codedStream->WriteLittleEndian32(magicNumber);
679397Sandreas.hansson@arm.com
689397Sandreas.hansson@arm.com    // Note that each type of stream (packet, instruction etc) should
699397Sandreas.hansson@arm.com    // add its own header and perform the appropriate checks
709397Sandreas.hansson@arm.com}
719397Sandreas.hansson@arm.com
729397Sandreas.hansson@arm.comProtoOutputStream::~ProtoOutputStream()
739397Sandreas.hansson@arm.com{
749397Sandreas.hansson@arm.com    delete codedStream;
759397Sandreas.hansson@arm.com    // As the compression is optional, see if the stream exists
769397Sandreas.hansson@arm.com    if (gzipStream != NULL)
779397Sandreas.hansson@arm.com        delete gzipStream;
789397Sandreas.hansson@arm.com    delete zeroCopyStream;
799397Sandreas.hansson@arm.com    fileStream.close();
809397Sandreas.hansson@arm.com}
819397Sandreas.hansson@arm.com
829397Sandreas.hansson@arm.comvoid
839397Sandreas.hansson@arm.comProtoOutputStream::write(const Message& msg)
849397Sandreas.hansson@arm.com{
859397Sandreas.hansson@arm.com    // Write the size of the message to the stream
869397Sandreas.hansson@arm.com    codedStream->WriteVarint32(msg.ByteSize());
879397Sandreas.hansson@arm.com
889397Sandreas.hansson@arm.com    // Write the message itself to the stream
899397Sandreas.hansson@arm.com    if (!msg.SerializeToCodedStream(codedStream))
909397Sandreas.hansson@arm.com        panic("Unable to write message to coded stream\n");
919397Sandreas.hansson@arm.com}
929399Sandreas.hansson@arm.com
939399Sandreas.hansson@arm.comProtoInputStream::ProtoInputStream(const string& filename) :
949464Sandreas.hansson@arm.com    fileStream(filename.c_str(), ios::in | ios::binary), fileName(filename),
959399Sandreas.hansson@arm.com    useGzip(false),
969399Sandreas.hansson@arm.com    zeroCopyStream(NULL), gzipStream(NULL), codedStream(NULL)
979399Sandreas.hansson@arm.com{
989399Sandreas.hansson@arm.com    if (!fileStream.good())
999399Sandreas.hansson@arm.com        panic("Could not open %s for reading\n", filename);
1009399Sandreas.hansson@arm.com
1019399Sandreas.hansson@arm.com    // check the magic number to see if this is a gzip stream
1029399Sandreas.hansson@arm.com    unsigned char bytes[2];
1039399Sandreas.hansson@arm.com    fileStream.read((char*) bytes, 2);
1049399Sandreas.hansson@arm.com    useGzip = fileStream.good() && bytes[0] == 0x1f && bytes[1] == 0x8b;
1059399Sandreas.hansson@arm.com
1069399Sandreas.hansson@arm.com    // seek to the start of the input file and clear any flags
1079399Sandreas.hansson@arm.com    fileStream.clear();
1089399Sandreas.hansson@arm.com    fileStream.seekg(0, ifstream::beg);
1099399Sandreas.hansson@arm.com
1109399Sandreas.hansson@arm.com    createStreams();
1119399Sandreas.hansson@arm.com}
1129399Sandreas.hansson@arm.com
1139399Sandreas.hansson@arm.comvoid
1149399Sandreas.hansson@arm.comProtoInputStream::createStreams()
1159399Sandreas.hansson@arm.com{
1169399Sandreas.hansson@arm.com    // All streams should be NULL at this point
1179399Sandreas.hansson@arm.com    assert(zeroCopyStream == NULL && gzipStream == NULL &&
1189399Sandreas.hansson@arm.com           codedStream == NULL);
1199399Sandreas.hansson@arm.com
1209399Sandreas.hansson@arm.com    // Wrap the input file in a zero copy stream, that in turn is
1219399Sandreas.hansson@arm.com    // wrapped in a gzip stream if the filename ends with .gz. The
1229399Sandreas.hansson@arm.com    // latter stream is in turn wrapped in a coded stream
1239399Sandreas.hansson@arm.com    zeroCopyStream = new io::IstreamInputStream(&fileStream);
1249399Sandreas.hansson@arm.com    if (useGzip) {
1259399Sandreas.hansson@arm.com        gzipStream = new io::GzipInputStream(zeroCopyStream);
1269399Sandreas.hansson@arm.com        codedStream = new io::CodedInputStream(gzipStream);
1279399Sandreas.hansson@arm.com    } else {
1289399Sandreas.hansson@arm.com        codedStream = new io::CodedInputStream(zeroCopyStream);
1299399Sandreas.hansson@arm.com    }
1309399Sandreas.hansson@arm.com
1319399Sandreas.hansson@arm.com    uint32_t magic_check;
1329399Sandreas.hansson@arm.com    if (!codedStream->ReadLittleEndian32(&magic_check) ||
1339399Sandreas.hansson@arm.com        magic_check != magicNumber)
1349399Sandreas.hansson@arm.com        panic("Input file %s is not a valid gem5 proto format.\n",
1359399Sandreas.hansson@arm.com              fileName);
1369399Sandreas.hansson@arm.com}
1379399Sandreas.hansson@arm.com
1389399Sandreas.hansson@arm.comvoid
1399399Sandreas.hansson@arm.comProtoInputStream::destroyStreams()
1409399Sandreas.hansson@arm.com{
1419399Sandreas.hansson@arm.com    delete codedStream;
1429399Sandreas.hansson@arm.com    codedStream = NULL;
1439399Sandreas.hansson@arm.com    // As the compression is optional, see if the stream exists
1449399Sandreas.hansson@arm.com    if (gzipStream != NULL) {
1459399Sandreas.hansson@arm.com        delete gzipStream;
1469399Sandreas.hansson@arm.com        gzipStream = NULL;
1479399Sandreas.hansson@arm.com    }
1489399Sandreas.hansson@arm.com    delete zeroCopyStream;
1499399Sandreas.hansson@arm.com    zeroCopyStream = NULL;
1509399Sandreas.hansson@arm.com}
1519399Sandreas.hansson@arm.com
1529399Sandreas.hansson@arm.com
1539399Sandreas.hansson@arm.comProtoInputStream::~ProtoInputStream()
1549399Sandreas.hansson@arm.com{
1559399Sandreas.hansson@arm.com    destroyStreams();
1569399Sandreas.hansson@arm.com    fileStream.close();
1579399Sandreas.hansson@arm.com}
1589399Sandreas.hansson@arm.com
1599399Sandreas.hansson@arm.com
1609399Sandreas.hansson@arm.comvoid
1619399Sandreas.hansson@arm.comProtoInputStream::reset()
1629399Sandreas.hansson@arm.com{
1639399Sandreas.hansson@arm.com    destroyStreams();
1649399Sandreas.hansson@arm.com    // seek to the start of the input file and clear any flags
1659399Sandreas.hansson@arm.com    fileStream.clear();
1669399Sandreas.hansson@arm.com    fileStream.seekg(0, ifstream::beg);
1679399Sandreas.hansson@arm.com    createStreams();
1689399Sandreas.hansson@arm.com}
1699399Sandreas.hansson@arm.com
1709399Sandreas.hansson@arm.combool
1719399Sandreas.hansson@arm.comProtoInputStream::read(Message& msg)
1729399Sandreas.hansson@arm.com{
1739399Sandreas.hansson@arm.com    // Read a message from the stream by getting the size, using it as
1749399Sandreas.hansson@arm.com    // a limit when parsing the message, then popping the limit again
1759399Sandreas.hansson@arm.com    uint32_t size;
1769399Sandreas.hansson@arm.com    if (codedStream->ReadVarint32(&size)) {
1779399Sandreas.hansson@arm.com        io::CodedInputStream::Limit limit = codedStream->PushLimit(size);
1789399Sandreas.hansson@arm.com        if (msg.ParseFromCodedStream(codedStream)) {
1799399Sandreas.hansson@arm.com            codedStream->PopLimit(limit);
1809399Sandreas.hansson@arm.com            // All went well, the message is parsed and the limit is
1819399Sandreas.hansson@arm.com            // popped again
1829399Sandreas.hansson@arm.com            return true;
1839399Sandreas.hansson@arm.com        } else {
1849399Sandreas.hansson@arm.com            panic("Unable to read message from coded stream %s\n",
1859399Sandreas.hansson@arm.com                  fileName);
1869399Sandreas.hansson@arm.com        }
1879399Sandreas.hansson@arm.com    }
1889399Sandreas.hansson@arm.com
1899399Sandreas.hansson@arm.com    return false;
1909399Sandreas.hansson@arm.com}
191