Initial implementation of serialization of basic types and namespaces.

* src/Makefile.am: Add abg-writer.{h,cc} and abg-config.{h,cc}.
	* src/abg-config.{h,cc}: New files.
	* src/abg-corpus.h (abi_corpus::decls_type): New typedef.
	(abi_corpus::{add,get_decls,get_loc_mgr}): Fix style.
	(abi_corpus::is_empty): Declare new function.
	* src/abg-corpus.cc (abi_corpus::add): really add the declaration
	to the corpus.
	(abi_corpus::is_empty): Define new function.
	* src/abg-ir.{h,cc} (location_manager::expand_location): Consti-fy
	this function.
	* src/abg-reader.cc (read_file): Add a corpus parameter.
	* src/abg-serialize.cc: Delete this file.
	* src/abg-writer.h (write_to_ostream): Rename write into this.
	Make it take a corpus and an ostream as parameters.
	* abg-writer.cc: New file.
This commit is contained in:
Dodji Seketeli 2013-03-21 14:43:30 +01:00
parent 8e225db39a
commit a80b09f912
12 changed files with 431 additions and 17 deletions

View File

@ -9,14 +9,17 @@ $(h)/abg-reader.h \
$(h)/abg-corpus.h \
$(h)/abg-libxml-utils.h \
$(h)/abg-hash.h \
$(h)/abg-writer.h
$(h)/abg-writer.h \
$(h)/abg-config.h
libabigail_la_SOURCES = $(headers) \
$(h)/abg-ir.cc \
$(h)/abg-reader.cc \
$(h)/abg-corpus.cc \
$(h)/abg-libxml-utils.cc \
$(h)/abg-hash.cc
$(h)/abg-hash.cc \
$(h)/abg-writer.cc \
$(h)/abg-config.cc
libabigail_la_LDFLAGS=@ABIGAIL_LIBS@ -Wl,--as-needed

51
src/abg-config.cc Normal file
View File

@ -0,0 +1,51 @@
// -*- mode: C++ -*-
#include "abg-config.h"
namespace abigail
{
config::config()
: m_format_minor(0),
m_format_major(1),// The version number of the serialization
// format.
m_xml_element_indent(2)
{
}
unsigned char
config::get_format_minor_version_number() const
{
return m_format_minor;
}
void
config::set_format_minor_version_number(unsigned char v)
{
m_format_minor = v;
}
unsigned char
config::get_format_major_version_number() const
{
return m_format_major;
}
void
config::set_format_major_version_number(unsigned char v)
{
m_format_major= v;
}
unsigned
config::get_xml_element_indent() const
{
return m_xml_element_indent;
}
void
config::set_xml_element_indent(unsigned indent)
{
m_xml_element_indent = indent;
}
}//end namespace abigail

41
src/abg-config.h Normal file
View File

@ -0,0 +1,41 @@
// -*- Mode: C++ -*-
#ifndef __ABG_CONFIG_H__
#define __ABG_CONFIG_H__
namespace abigail
{
/// This type abstracts the configuration information of the library.
class config
{
public:
config();
unsigned char
get_format_minor_version_number() const;
void
set_format_minor_version_number(unsigned char);
unsigned char
get_format_major_version_number() const;
void
set_format_major_version_number(unsigned char);
unsigned
get_xml_element_indent() const;
void
set_xml_element_indent(unsigned);
private:
unsigned char m_format_minor;
unsigned char m_format_major;
unsigned m_xml_element_indent;
};//end class config
}//end namespace abigail
#endif //__ABG_CONFIG_H__

View File

@ -13,7 +13,7 @@ abi_corpus::abi_corpus(const std::string& name)
void
abi_corpus::add(const shared_ptr<decl_base> declaration)
{
m_members;
m_members.push_back(declaration);
}
const std::list<shared_ptr<decl_base> >&
@ -34,4 +34,10 @@ abi_corpus::get_loc_mgr()
return m_loc_mgr;
}
bool
abi_corpus::is_empty() const
{
return m_members.empty();
}
}//end namespace abigail

View File

@ -18,12 +18,24 @@ class abi_corpus
abi_corpus();
public:
typedef std::list<shared_ptr<decl_base> > decls_type;
abi_corpus(const std::string& name);
void add(const shared_ptr<decl_base> declaration);
const std::list<shared_ptr<decl_base> >& get_decls() const;
location_manager& get_loc_mgr();
const location_manager& get_loc_mgr() const;
void
add(const shared_ptr<decl_base> declaration);
const std::list<shared_ptr<decl_base> >&
get_decls() const;
location_manager&
get_loc_mgr();
const location_manager&
get_loc_mgr() const;
bool
is_empty() const;
private:
std::string m_name;

View File

@ -94,7 +94,6 @@ location_manager::create_new_location(const std::string& file_path,
m_priv->locs.end(),
l);
unsigned opaque = 0;
if (i == m_priv->locs.end())
{
m_priv->locs.push_back(l);
@ -127,7 +126,7 @@ void
location_manager::expand_location(const location location,
std::string& path,
unsigned& line,
unsigned& column)
unsigned& column) const
{
expanded_location &l = m_priv->locs[location.m_value];
path = l.m_path;

View File

@ -20,7 +20,7 @@ using std::string;
namespace abigail
{
/// \brief The source location of a token.
///
///
/// This represents the location of a token coming from a given ABI
/// Corpus. This location is actually an abstraction of cursor in the
/// table of all the locations of all the tokens of the ABI Corpus.
@ -78,7 +78,7 @@ public:
expand_location(const location location,
std::string& path,
unsigned& line,
unsigned& column);
unsigned& column) const;
};
class scope_decl;

View File

@ -129,7 +129,7 @@ static bool handle_type_decl(read_context&, abi_corpus&);
static bool handle_namespace_decl(read_context&, abi_corpus&);
bool
read_file(string& file_path,
read_file(const string& file_path,
abi_corpus& corpus)
{
read_context read_ctxt(xml::new_reader_from_file(file_path));

View File

@ -8,7 +8,7 @@ namespace abigail
{
namespace reader
{
bool read_file(std::string& file_path,
bool read_file(const std::string& file_path,
abi_corpus& abi_corpus);
}// end namespace reader

View File

297
src/abg-writer.cc Normal file
View File

@ -0,0 +1,297 @@
// -*- mode: C++ -*-
#include <ostream>
#include <sstream>
#include <tr1/memory>
#include "abg-writer.h"
#include "abg-config.h"
using std::tr1::shared_ptr;
using std::tr1::dynamic_pointer_cast;
using std::ostream;
using std::ostringstream;
using std::list;
namespace abigail
{
namespace writer
{
class id_manager
{
unsigned long long
get_new_id()
{
return ++m_cur_id;
}
public:
id_manager()
: m_cur_id(0)
{
}
/// Return a unique string representing a numerical id.
string
get_id()
{
ostringstream o;
o << get_new_id();
return o.str();
}
/// Return a unique string representing a numerical ID, prefixed by
/// #prefix.
///
/// \param prefix the prefix of the returned unique id.
string
get_id_with_prefix(const string& prefix)
{
ostringstream o;
o << prefix << get_new_id();
return o.str();
}
private:
unsigned long long m_cur_id;
};//end class id_manager
class write_context
{
write_context();
public:
write_context(ostream& os)
: m_ostream(os)
{
}
const config&
get_config() const
{
return m_config;
}
ostream&
get_ostream()
{
return m_ostream;
}
id_manager&
get_id_manager()
{
return m_id_manager;
}
private:
id_manager m_id_manager;
config m_config;
ostream& m_ostream;
};//end write_context
static bool write_corpus(const abi_corpus&,
write_context&,
unsigned);
static bool write_decl(const shared_ptr<decl_base>,
const abi_corpus&,
write_context&,
unsigned);
static bool write_type_decl(const shared_ptr<type_decl>,
const abi_corpus&,
write_context&,
unsigned);
static bool write_namespace_decl(const shared_ptr<namespace_decl>,
const abi_corpus&,
write_context&,
unsigned);
/// Serialize an abi corpus into an output stream.
///
/// \param corpus the corpus to serialize
///
/// \param out the output stream.
///
/// \return true upon successful completion, false otherwise.
bool
write_to_ostream(const abi_corpus& corpus,
ostream &out)
{
write_context ctxt(out);
return write_corpus(corpus, ctxt, /*indent=*/0);
}
/// Serialize a pointer to an of decl_base into an output stream.
///
/// \param decl, the pointer to decl_base to serialize
///
/// \param corpus the abi corpus the decl belongs to.
///
/// \param ctxt the context of the serialization. It contains e.g, the
/// output stream to serialize to.
///
/// \param indent how many indentation spaces to use during the
/// serialization.
///
/// \return true upon successful completion, false otherwise.
static bool
write_decl(const shared_ptr<decl_base> decl,
const abi_corpus& corpus,
write_context& ctxt,
unsigned indent)
{
if (write_type_decl(dynamic_pointer_cast<type_decl> (decl),
corpus, ctxt, indent))
return true;
if (write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl),
corpus, ctxt, indent))
return true;
return false;
}
/// Serialize an abi corpus into an output stream.
///
/// \param a corpus the abi corpus to serialize.
///
/// \param ctxt the context of the serialization. It contains e.g,
/// the output stream to serialize to.
///
/// \param indent how many indentation spaces to use during the
/// serialization.
///
/// \return true upon successful completion, false otherwise.
static bool
write_corpus(const abi_corpus& corpus, write_context& ctxt, unsigned indent)
{
ostream &o = ctxt.get_ostream();
const config &c = ctxt.get_config();
for (unsigned i = 0; i < indent; ++i)
o << ' ';
o << "<abi-instr version='"
<< c.get_format_major_version_number()
<< "." << c.get_format_minor_version_number()
<< "'";
if (corpus.is_empty())
{
o << "/>";
return true;
}
for (abi_corpus::decls_type::const_iterator i = corpus.get_decls().begin();
i != corpus.get_decls().end();
++i)
{
o << "\n";
write_decl(*i, corpus, ctxt,
indent + c.get_xml_element_indent());
}
return true;
}
/// Serialize a pointer to an instance of basic type declaration, into
/// an output stream.
///
/// \param d the basic type declaration to serialize.
///
/// \param corpus the instance of abi corpus the declaration belongs
/// to.
///
/// \param ctxt the context of the serialization. It contains e.g, the
/// output stream to serialize to.
///
/// \param indent how many indentation spaces to use during the
/// serialization.
///
/// \return true upon successful completion, false otherwise.
static bool
write_type_decl(const shared_ptr<type_decl> d,
const abi_corpus& corpus,
write_context& ctxt,
unsigned indent)
{
ostream &o = ctxt.get_ostream();
for (unsigned i = 0; i < indent; ++i)
o << ' ';
o << "<type-decl name='" << d->get_name() << "'"
<< "xml:id='"
<< ctxt.get_id_manager().get_id_with_prefix("type-decl-")
<< "'";
size_t size_in_bits = d->get_size_in_bits();
if (size_in_bits)
o << " size-in-bits='" << size_in_bits << "'";
size_t alignment_in_bits = d->get_alignment_in_bits();
if (alignment_in_bits)
o << " alignment-in-bits='" << alignment_in_bits << "'";
location loc = d->get_location();
if (loc)
{
string path;
unsigned line = 0, column = 0;
corpus.get_loc_mgr().expand_location(loc, path, line, column);
o << " filepath='" << path << "'"
<< " line='" << line << "'"
<< " column='" << column << "'";
}
o<< "/>";
return true;
}
/// Serialize a namespace declaration int an output stream.
///
/// \param decl the namespace declaration to serialize.
///
/// \param corpus the instance of abi corpus the declaration belongs
/// to.
///
/// \param ctxt the context of the serialization. It contains e.g, the
/// output stream to serialize to.
///
/// \param indent how many indentation spaces to use during the
/// serialization.
///
/// \return true upon successful completion, false otherwise.
static bool
write_namespace_decl(const shared_ptr<namespace_decl> decl,
const abi_corpus& corpus,
write_context& ctxt,
unsigned indent)
{
ostream &o = ctxt.get_ostream();
const config &c = ctxt.get_config();
for (unsigned i = 0; i < indent; ++i)
o << ' ';
o << "<namespace-decl name='" << decl->get_name() << "'>";
for (list<shared_ptr<decl_base> >::const_iterator i =
decl->get_member_decls ().begin();
i != decl->get_member_decls ().end();
++i)
{
o << "\n";
write_decl(*i, corpus, ctxt,
indent + c.get_xml_element_indent());
}
o << "</namespace-decl-name>";
return true;
}
}//end namespace writer
}//end namespace abigail

View File

@ -3,13 +3,18 @@
#ifndef __ABG_WRITER_H__
#define __ABG_WRITER_H__
#include "abg-ir.h"
#include <ostream>
#include "abg-corpus.h"
namespace abigail
{
namespace writer
{
bool write(const namespace_decl ns);
}//writer
}
bool write_to_ostream(const abi_corpus& corpus,
std::ostream& out);
}//end namespace writer
}// end namespace abigail
#endif //__ABG_WRITER_H__