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 4011793Sbrandon.potter@amd.com#include "proto/protoio.hh" 4111793Sbrandon.potter@amd.com 4212334Sgabeblack@google.com#include "base/logging.hh" 439397Sandreas.hansson@arm.com 449397Sandreas.hansson@arm.comusing namespace std; 459397Sandreas.hansson@arm.comusing namespace google::protobuf; 469397Sandreas.hansson@arm.com 479397Sandreas.hansson@arm.comProtoOutputStream::ProtoOutputStream(const string& filename) : 489397Sandreas.hansson@arm.com fileStream(filename.c_str(), ios::out | ios::binary | ios::trunc), 499705Sandreas.hansson@arm.com wrappedFileStream(NULL), gzipStream(NULL), zeroCopyStream(NULL) 509397Sandreas.hansson@arm.com{ 519397Sandreas.hansson@arm.com if (!fileStream.good()) 529397Sandreas.hansson@arm.com panic("Could not open %s for writing\n", filename); 539397Sandreas.hansson@arm.com 549397Sandreas.hansson@arm.com // Wrap the output file in a zero copy stream, that in turn is 559397Sandreas.hansson@arm.com // wrapped in a gzip stream if the filename ends with .gz. The 569397Sandreas.hansson@arm.com // latter stream is in turn wrapped in a coded stream 579705Sandreas.hansson@arm.com wrappedFileStream = new io::OstreamOutputStream(&fileStream); 589397Sandreas.hansson@arm.com if (filename.find_last_of('.') != string::npos && 599397Sandreas.hansson@arm.com filename.substr(filename.find_last_of('.') + 1) == "gz") { 609705Sandreas.hansson@arm.com gzipStream = new io::GzipOutputStream(wrappedFileStream); 619705Sandreas.hansson@arm.com zeroCopyStream = gzipStream; 629397Sandreas.hansson@arm.com } else { 639705Sandreas.hansson@arm.com zeroCopyStream = wrappedFileStream; 649397Sandreas.hansson@arm.com } 659397Sandreas.hansson@arm.com 669399Sandreas.hansson@arm.com // Write the magic number to the file 679705Sandreas.hansson@arm.com io::CodedOutputStream codedStream(zeroCopyStream); 689705Sandreas.hansson@arm.com codedStream.WriteLittleEndian32(magicNumber); 699397Sandreas.hansson@arm.com 709397Sandreas.hansson@arm.com // Note that each type of stream (packet, instruction etc) should 719397Sandreas.hansson@arm.com // add its own header and perform the appropriate checks 729397Sandreas.hansson@arm.com} 739397Sandreas.hansson@arm.com 749397Sandreas.hansson@arm.comProtoOutputStream::~ProtoOutputStream() 759397Sandreas.hansson@arm.com{ 769397Sandreas.hansson@arm.com // As the compression is optional, see if the stream exists 779397Sandreas.hansson@arm.com if (gzipStream != NULL) 789397Sandreas.hansson@arm.com delete gzipStream; 799705Sandreas.hansson@arm.com delete wrappedFileStream; 809397Sandreas.hansson@arm.com fileStream.close(); 819397Sandreas.hansson@arm.com} 829397Sandreas.hansson@arm.com 839397Sandreas.hansson@arm.comvoid 849397Sandreas.hansson@arm.comProtoOutputStream::write(const Message& msg) 859397Sandreas.hansson@arm.com{ 869705Sandreas.hansson@arm.com // Due to the byte limit of the coded stream we create it for 879705Sandreas.hansson@arm.com // every single mesage (based on forum discussions around the size 889705Sandreas.hansson@arm.com // limitation) 899705Sandreas.hansson@arm.com io::CodedOutputStream codedStream(zeroCopyStream); 909705Sandreas.hansson@arm.com 919397Sandreas.hansson@arm.com // Write the size of the message to the stream 929705Sandreas.hansson@arm.com codedStream.WriteVarint32(msg.ByteSize()); 939397Sandreas.hansson@arm.com 949397Sandreas.hansson@arm.com // Write the message itself to the stream 959705Sandreas.hansson@arm.com msg.SerializeWithCachedSizes(&codedStream); 969397Sandreas.hansson@arm.com} 979399Sandreas.hansson@arm.com 989399Sandreas.hansson@arm.comProtoInputStream::ProtoInputStream(const string& filename) : 999464Sandreas.hansson@arm.com fileStream(filename.c_str(), ios::in | ios::binary), fileName(filename), 1009399Sandreas.hansson@arm.com useGzip(false), 1019705Sandreas.hansson@arm.com wrappedFileStream(NULL), gzipStream(NULL), zeroCopyStream(NULL) 1029399Sandreas.hansson@arm.com{ 1039399Sandreas.hansson@arm.com if (!fileStream.good()) 1049399Sandreas.hansson@arm.com panic("Could not open %s for reading\n", filename); 1059399Sandreas.hansson@arm.com 1069399Sandreas.hansson@arm.com // check the magic number to see if this is a gzip stream 1079399Sandreas.hansson@arm.com unsigned char bytes[2]; 1089399Sandreas.hansson@arm.com fileStream.read((char*) bytes, 2); 1099399Sandreas.hansson@arm.com useGzip = fileStream.good() && bytes[0] == 0x1f && bytes[1] == 0x8b; 1109399Sandreas.hansson@arm.com 1119399Sandreas.hansson@arm.com // seek to the start of the input file and clear any flags 1129399Sandreas.hansson@arm.com fileStream.clear(); 1139399Sandreas.hansson@arm.com fileStream.seekg(0, ifstream::beg); 1149399Sandreas.hansson@arm.com 1159399Sandreas.hansson@arm.com createStreams(); 1169399Sandreas.hansson@arm.com} 1179399Sandreas.hansson@arm.com 1189399Sandreas.hansson@arm.comvoid 1199399Sandreas.hansson@arm.comProtoInputStream::createStreams() 1209399Sandreas.hansson@arm.com{ 1219399Sandreas.hansson@arm.com // All streams should be NULL at this point 1229705Sandreas.hansson@arm.com assert(wrappedFileStream == NULL && gzipStream == NULL && 1239705Sandreas.hansson@arm.com zeroCopyStream == NULL); 1249399Sandreas.hansson@arm.com 1259399Sandreas.hansson@arm.com // Wrap the input file in a zero copy stream, that in turn is 1269399Sandreas.hansson@arm.com // wrapped in a gzip stream if the filename ends with .gz. The 1279399Sandreas.hansson@arm.com // latter stream is in turn wrapped in a coded stream 1289705Sandreas.hansson@arm.com wrappedFileStream = new io::IstreamInputStream(&fileStream); 1299399Sandreas.hansson@arm.com if (useGzip) { 1309705Sandreas.hansson@arm.com gzipStream = new io::GzipInputStream(wrappedFileStream); 1319705Sandreas.hansson@arm.com zeroCopyStream = gzipStream; 1329399Sandreas.hansson@arm.com } else { 1339705Sandreas.hansson@arm.com zeroCopyStream = wrappedFileStream; 1349399Sandreas.hansson@arm.com } 1359399Sandreas.hansson@arm.com 1369399Sandreas.hansson@arm.com uint32_t magic_check; 1379705Sandreas.hansson@arm.com io::CodedInputStream codedStream(zeroCopyStream); 1389705Sandreas.hansson@arm.com if (!codedStream.ReadLittleEndian32(&magic_check) || 1399399Sandreas.hansson@arm.com magic_check != magicNumber) 1409399Sandreas.hansson@arm.com panic("Input file %s is not a valid gem5 proto format.\n", 1419399Sandreas.hansson@arm.com fileName); 1429399Sandreas.hansson@arm.com} 1439399Sandreas.hansson@arm.com 1449399Sandreas.hansson@arm.comvoid 1459399Sandreas.hansson@arm.comProtoInputStream::destroyStreams() 1469399Sandreas.hansson@arm.com{ 1479399Sandreas.hansson@arm.com // As the compression is optional, see if the stream exists 1489399Sandreas.hansson@arm.com if (gzipStream != NULL) { 1499399Sandreas.hansson@arm.com delete gzipStream; 1509399Sandreas.hansson@arm.com gzipStream = NULL; 1519399Sandreas.hansson@arm.com } 1529705Sandreas.hansson@arm.com delete wrappedFileStream; 1539705Sandreas.hansson@arm.com wrappedFileStream = NULL; 1549705Sandreas.hansson@arm.com 1559399Sandreas.hansson@arm.com zeroCopyStream = NULL; 1569399Sandreas.hansson@arm.com} 1579399Sandreas.hansson@arm.com 1589399Sandreas.hansson@arm.com 1599399Sandreas.hansson@arm.comProtoInputStream::~ProtoInputStream() 1609399Sandreas.hansson@arm.com{ 1619399Sandreas.hansson@arm.com destroyStreams(); 1629399Sandreas.hansson@arm.com fileStream.close(); 1639399Sandreas.hansson@arm.com} 1649399Sandreas.hansson@arm.com 1659399Sandreas.hansson@arm.com 1669399Sandreas.hansson@arm.comvoid 1679399Sandreas.hansson@arm.comProtoInputStream::reset() 1689399Sandreas.hansson@arm.com{ 1699399Sandreas.hansson@arm.com destroyStreams(); 1709399Sandreas.hansson@arm.com // seek to the start of the input file and clear any flags 1719399Sandreas.hansson@arm.com fileStream.clear(); 1729399Sandreas.hansson@arm.com fileStream.seekg(0, ifstream::beg); 1739399Sandreas.hansson@arm.com createStreams(); 1749399Sandreas.hansson@arm.com} 1759399Sandreas.hansson@arm.com 1769399Sandreas.hansson@arm.combool 1779399Sandreas.hansson@arm.comProtoInputStream::read(Message& msg) 1789399Sandreas.hansson@arm.com{ 1799399Sandreas.hansson@arm.com // Read a message from the stream by getting the size, using it as 1809399Sandreas.hansson@arm.com // a limit when parsing the message, then popping the limit again 1819399Sandreas.hansson@arm.com uint32_t size; 1829705Sandreas.hansson@arm.com 1839705Sandreas.hansson@arm.com // Due to the byte limit of the coded stream we create it for 1849705Sandreas.hansson@arm.com // every single mesage (based on forum discussions around the size 1859705Sandreas.hansson@arm.com // limitation) 1869705Sandreas.hansson@arm.com io::CodedInputStream codedStream(zeroCopyStream); 1879705Sandreas.hansson@arm.com if (codedStream.ReadVarint32(&size)) { 1889705Sandreas.hansson@arm.com io::CodedInputStream::Limit limit = codedStream.PushLimit(size); 1899705Sandreas.hansson@arm.com if (msg.ParseFromCodedStream(&codedStream)) { 1909705Sandreas.hansson@arm.com codedStream.PopLimit(limit); 1919399Sandreas.hansson@arm.com // All went well, the message is parsed and the limit is 1929399Sandreas.hansson@arm.com // popped again 1939399Sandreas.hansson@arm.com return true; 1949399Sandreas.hansson@arm.com } else { 1959399Sandreas.hansson@arm.com panic("Unable to read message from coded stream %s\n", 1969399Sandreas.hansson@arm.com fileName); 1979399Sandreas.hansson@arm.com } 1989399Sandreas.hansson@arm.com } 1999399Sandreas.hansson@arm.com 2009399Sandreas.hansson@arm.com return false; 2019399Sandreas.hansson@arm.com} 202