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