1#ifndef ROSE_BinaryAnalysis_SerialIo_H 
    2#define ROSE_BinaryAnalysis_SerialIo_H 
    3#include <featureTests.h> 
    4#ifdef ROSE_ENABLE_BINARY_ANALYSIS 
   10#ifdef ROSE_ENABLE_BOOST_SERIALIZATION 
   11#include <boost/archive/binary_iarchive.hpp> 
   12#include <boost/archive/binary_oarchive.hpp> 
   13#include <boost/archive/text_iarchive.hpp> 
   14#include <boost/archive/text_oarchive.hpp> 
   15#include <boost/archive/xml_iarchive.hpp> 
   16#include <boost/archive/xml_oarchive.hpp> 
   17#include <boost/iostreams/device/file_descriptor.hpp> 
   18#include <boost/iostreams/stream.hpp> 
   21#include <Rose/Progress.h> 
   22#include <Rose/Exception.h> 
   23#include <ROSE_UNUSED.h> 
   25#include <Sawyer/Message.h> 
   26#include <Sawyer/ProgressBar.h> 
   27#include <Sawyer/Synchronization.h> 
   29#include <boost/filesystem.hpp> 
   30#include <boost/lexical_cast.hpp> 
   31#include <boost/thread.hpp> 
   34namespace BinaryAnalysis {
 
  132    mutable SAWYER_THREAD_TRAITS::Mutex mutex_; 
 
  150          progressBar_(
mlog[
Sawyer::Message::MARCH]), fd_(-1) {
 
  152        progressBar_.
suffix(
" bytes");
 
  205    virtual void open(
const boost::filesystem::path&) = 0;
 
  235    void setIsOpen(
bool b);
 
 
  258#ifdef ROSE_ENABLE_BOOST_SERIALIZATION 
  259    boost::iostreams::file_descriptor_sink device_;
 
  260    boost::iostreams::stream<boost::iostreams::file_descriptor_sink> file_;
 
  261    boost::archive::binary_oarchive *binary_archive_;
 
  262    boost::archive::text_oarchive *text_archive_;
 
  263    boost::archive::xml_oarchive *xml_archive_;
 
  267#ifdef ROSE_ENABLE_BOOST_SERIALIZATION 
  268    SerialOutput(): binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
 
  275    void open(
const boost::filesystem::path &fileName) 
override;
 
  312    void saveAstHelper(
SgNode*);
 
  332            throw Exception(
"cannot save object when no file is open");
 
  334            throw Exception(
"cannot save object because stream is in error state");
 
  336#ifndef ROSE_ENABLE_BOOST_SERIALIZATION 
  337        ROSE_UNUSED(objectTypeId);
 
  339        throw Exception(
"binary state files are not supported in this configuration");
 
  340#elif defined(ROSE_DEBUG_SERIAL_IO) 
  341        std::string errorMessage;
 
  342        asyncSave(objectTypeId, 
object, &errorMessage);
 
  345        std::string errorMessage;
 
  346        boost::thread worker(startWorker<T>, 
this, objectTypeId, &
object, &errorMessage);
 
  348        progressBar_.
prefix(
"writing");
 
  349        while (!worker.try_join_for(timeout)) {
 
  350            off_t cur = ::lseek(fd_, 0, SEEK_CUR);
 
  354                progressBar_.
value(cur);
 
  359        if (!errorMessage.empty())
 
 
  366    static void startWorker(
SerialOutput *saver, 
Savable objectTypeId, 
const T *
object, std::string *errorMessage) {
 
  367        ASSERT_not_null(
object);
 
  368        saver->asyncSave(objectTypeId, *
object, errorMessage);
 
  373    void asyncSave(
Savable objectTypeId, 
const T &
object, std::string *errorMessage) {
 
  374        ASSERT_not_null(errorMessage);
 
  375#ifndef ROSE_ENABLE_BOOST_SERIALIZATION 
  376        ROSE_UNUSED(objectTypeId);
 
  378        ASSERT_not_reachable(
"not supported in this configuration");
 
  380#if !defined(ROSE_DEBUG_SERIAL_IO) 
  383            std::string roseVersion = ROSE_PACKAGE_VERSION;
 
  387                    ASSERT_not_null(binary_archive_);
 
  388                    *binary_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
 
  389                    *binary_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
 
  390                    *binary_archive_ <<BOOST_SERIALIZATION_NVP(
object);
 
  393                    ASSERT_not_null(text_archive_);
 
  394                    *text_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
 
  395                    *text_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
 
  396                    *text_archive_ <<BOOST_SERIALIZATION_NVP(
object);
 
  399                    ASSERT_not_null(xml_archive_);
 
  400                    *xml_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
 
  401                    *xml_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
 
  402                    *xml_archive_ <<BOOST_SERIALIZATION_NVP(
object);
 
  406#if !defined(ROSE_DEBUG_SERIAL_IO) 
  407        } 
catch (std::exception &e) {
 
  408            *errorMessage = e.what();
 
  410            *errorMessage = 
"failed to write object to output stream";
 
 
  431#ifdef ROSE_ENABLE_BOOST_SERIALIZATION 
  433    boost::iostreams::file_descriptor_source device_;
 
  434    boost::iostreams::stream<boost::iostreams::file_descriptor_source> file_;
 
  435    boost::archive::binary_iarchive *binary_archive_;
 
  436    boost::archive::text_iarchive *text_archive_;
 
  437    boost::archive::xml_iarchive *xml_archive_;
 
  441#ifdef ROSE_ENABLE_BOOST_SERIALIZATION 
  442    SerialInput(): fileSize_(0), binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
 
  449    void open(
const boost::filesystem::path &fileName) 
override;
 
  493        loadObject<T>(objectTypeId, 
object);
 
 
  499            throw Exception(
"cannot load object when no file is open");
 
  501#ifndef ROSE_ENABLE_BOOST_SERIALIZATION 
  502        ROSE_UNUSED(objectTypeId);
 
  504        throw Exception(
"binary state files are not supported in this configuration");
 
  507            throw Exception(
"cannot read object because stream is in error state");
 
  509            throw Exception(
"unexpected object type (expected " + boost::lexical_cast<std::string>(objectTypeId) +
 
  510                            " but read " + boost::lexical_cast<std::string>(
objectType()) + 
")");
 
  513        std::string errorMessage;
 
  514#ifdef ROSE_DEBUG_SERIAL_IO 
  515        asyncLoad(
object, &errorMessage);
 
  517        boost::thread worker(startWorker<T>, 
this, &
object, &errorMessage);
 
  519        progressBar_.
prefix(
"reading");
 
  520        while (!worker.try_join_for(timeout)) {
 
  522                off_t cur = ::lseek(fd_, 0, SEEK_CUR);
 
  524                    progressBar_.
value(cur);
 
  532        if (!errorMessage.empty())
 
 
  542    static void startWorker(
SerialInput *loader, T *
object, std::string *errorMessage) {
 
  543        loader->asyncLoad(*
object, errorMessage);
 
  548    void asyncLoad(T &
object, std::string *errorMessage) {
 
  549        ASSERT_not_null(errorMessage);
 
  550#ifndef ROSE_ENABLE_BOOST_SERIALIZATION 
  552        ASSERT_not_reachable(
"not supported in this configuration");
 
  554#if !defined(ROSE_DEBUG_SERIAL_IO) 
  557            std::string roseVersion;
 
  560                    ASSERT_not_null(binary_archive_);
 
  561                    *binary_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
 
  562                    checkCompatibility(roseVersion);
 
  563                    *binary_archive_ >>BOOST_SERIALIZATION_NVP(
object);
 
  566                    ASSERT_not_null(text_archive_);
 
  567                    *text_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
 
  568                    checkCompatibility(roseVersion);
 
  569                    *text_archive_ >>BOOST_SERIALIZATION_NVP(
object);
 
  572                    ASSERT_not_null(xml_archive_);
 
  573                    *xml_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
 
  574                    checkCompatibility(roseVersion);
 
  575                    *xml_archive_ >>BOOST_SERIALIZATION_NVP(
object);
 
  578#if !defined(ROSE_DEBUG_SERIAL_IO) 
  579        } 
catch (
const std::exception &e) {
 
  580            *errorMessage = e.what();
 
  582            *errorMessage = 
"failed to read object from input stream";
 
  588    void checkCompatibility(
const std::string &fileVersion);
 
  592    void advanceObjectType();
 
 
Errors thrown by this API.
 
Exception(const std::string &s)
Construct an exception with an error message.
 
Base class for binary state input and output.
 
virtual void close()=0
Detach a file.
 
virtual ~SerialIo()
Destructor.
 
Format
Format of the state file.
 
@ XML
The states are stored as XML, which is a very verbose and slow format.
 
@ TEXT
Textual binary state files use a custom format (Boost serialization format) that stores the data as A...
 
@ BINARY
Binary state files are smaller and faster than the other formats, but are not portable across archite...
 
void progress(const Progress::Ptr &)
Property: Progress reporter.
 
static Savable userSavable(unsigned offset)
Create a new Savable enum constant.
 
Format format() const
Property: File format.
 
Savable
Types of objects that can be saved.
 
@ END_OF_DATA
Marks the end of the data stream.
 
@ USER_DEFINED
First user-defined object number.
 
@ USER_DEFINED_LAST
Last user-defined object number.
 
@ ERROR
Marks that the stream has encountered an error condition.
 
@ PARTITIONER
Rose::BinaryAnalysis::Partitioner2::Partitioner.
 
@ AST
Abstract syntax tree.
 
@ NO_OBJECT
Object type for newly-initialized serializers.
 
Progress::Ptr progress() const
Property: Progress reporter.
 
virtual void open(const boost::filesystem::path &)=0
Attach a file.
 
Savable objectType() const
Type ID for next object.
 
bool isOpen() const
Whether a file is attached.
 
static Sawyer::Message::Facility mlog
Message facility.
 
void format(Format)
Property: File format.
 
Output binary analysis state.
 
SerialOutputPtr Ptr
Reference counting pointer.
 
static Ptr instance()
Factory method to create a new instance.
 
void saveObject(Savable objectTypeId, const T &object)
Save an object to the output stream.
 
void close() override
Detach a file.
 
void savePartitioner(const Partitioner2::PartitionerConstPtr &)
Save a binary analysis partitioner.
 
void open(const boost::filesystem::path &fileName) override
Attach a file.
 
void saveAst(SgAsmNode *)
Save a binary AST.
 
Base class for all ROSE exceptions.
 
A general, thread-safe way to report progress made on some task.
 
const std::string & prefix() const
String to show before the beginning of the bar.
 
Suffix suffix()
Property: suffix.
 
ValueType value() const
Value for the progress bar.
 
Base class for reference counted objects.
 
Reference-counting intrusive smart pointer.
 
Base class for all binary analysis IR nodes.
 
This class represents the base class for all IR nodes within Sage III.
 
Sawyer::SharedPointer< SerialOutput > SerialOutputPtr
Reference counting pointer.
 
Sawyer::SharedPointer< SerialIo > SerialIoPtr
Reference counting pointer.
 
Sawyer::SharedPointer< SerialInput > SerialInputPtr
Reference counting pointer.
 
double minimumUpdateInterval()
Minimum time between updates.
 
A single progress report.