OpenDDLParser: latest greatest.

pull/682/head
Kim Kulling 2015-10-01 20:29:15 +02:00
parent 7ed32fd5a9
commit 4a8b459706
10 changed files with 295 additions and 193 deletions

View File

@ -632,10 +632,13 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS})
SET ( openddl_parser_SRCS
../contrib/openddlparser/code/OpenDDLParser.cpp
../contrib/openddlparser/code/DDLNode.cpp
../contrib/openddlparser/code/OpenDDLCommon.cpp
../contrib/openddlparser/code/OpenDDLExport.cpp
../contrib/openddlparser/code/Value.cpp
../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
../contrib/openddlparser/include/openddlparser/DDLNode.h
../contrib/openddlparser/include/openddlparser/Value.h
)

View File

@ -49,11 +49,7 @@ static void releaseReferencedNames( Reference *ref ) {
return;
}
if( ref->m_referencedName ) {
for( size_t i = 0; i < ref->m_numRefs; i++ ) {
delete ref->m_referencedName;
}
}
delete ref;
}
DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent )
@ -143,6 +139,10 @@ bool DDLNode::hasProperty( const std::string &name ) {
return ( ddl_nullptr != prop );
}
bool DDLNode::hasProperties() const {
return( ddl_nullptr != m_properties );
}
Property *DDLNode::findPropertyByName( const std::string &name ) {
if( name.empty() ) {
return ddl_nullptr;

View File

@ -36,17 +36,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
BEGIN_ODDLPARSER_NS
static const char *Version = "0.1.0";
static const char *Version = "0.3.0";
namespace Grammar {
static const char * const OpenBracketToken = "{";
static const char * const CloseBracketToken = "}";
static const char * const OpenPropertyToken = "(";
static const char * const ClosePropertyToken = ")";
static const char * const BoolTrue = "true";
static const char * const BoolFalse = "false";
static const char * const RefToken = "ref";
static const char * const CommaSeparator = ",";
static const char *OpenBracketToken = "{";
static const char *CloseBracketToken = "}";
static const char *OpenPropertyToken = "(";
static const char *ClosePropertyToken = ")";
static const char *OpenArrayToken = "[";
static const char *CloseArrayToken = "]";
static const char *BoolTrue = "true";
static const char *BoolFalse = "false";
static const char *CommaSeparator = ",";
static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
"bool",
@ -66,7 +67,6 @@ namespace Grammar {
};
} // Namespace Grammar
static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
std::stringstream stream;
stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl;
@ -206,6 +206,18 @@ bool OpenDDLParser::parse() {
return true;
}
bool OpenDDLParser::exportContext( Context *ctx, const std::string &filename ) {
if( ddl_nullptr == ctx ) {
return false;
}
if( filename.empty() ) {
return false;
}
return false;
}
char *OpenDDLParser::parseNextNode( char *in, char *end ) {
in = parseHeader( in, end );
in = parseStructure( in, end );
@ -234,19 +246,19 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
in = lookForNextToken( in, end );
Property *first( ddl_nullptr );
if( ddl_nullptr != id ) {
if( *in == '(' ) {
if( *in == Grammar::OpenPropertyToken[ 0 ] ) {
in++;
Property *prop( ddl_nullptr ), *prev( ddl_nullptr );
while( *in != ')' && in != end ) {
while( *in != Grammar::ClosePropertyToken[ 0 ] && in != end ) {
in = OpenDDLParser::parseProperty( in, end, &prop );
in = lookForNextToken( in, end );
if( *in != ',' && *in != ')' ) {
logInvalidTokenError( in, ")", m_logCallback );
if( *in != Grammar::CommaSeparator[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] ) {
logInvalidTokenError( in, Grammar::ClosePropertyToken, m_logCallback );
return in;
}
if( ddl_nullptr != prop && *in != ',' ) {
if( ddl_nullptr != prop && *in != Grammar::CommaSeparator[ 0 ] ) {
if( ddl_nullptr == first ) {
first = prop;
}
@ -348,7 +360,7 @@ char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
if( Value::ddl_none != type ) {
// parse a primitive data type
in = lookForNextToken( in, end );
if( *in == '{' ) {
if( *in == Grammar::OpenBracketToken[ 0 ] ) {
Reference *refs( ddl_nullptr );
DataArrayList *dtArrayList( ddl_nullptr );
Value *values( ddl_nullptr );
@ -435,10 +447,10 @@ void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
newBuffer.push_back( buffer[ readIdx ] );
} else {
if( isComment<char>( c, end ) ) {
readIdx++;
++readIdx;
// skip the comment and the rest of the line
while( !isEndofLine( buffer[ readIdx ] ) ) {
readIdx++;
++readIdx;
}
}
}
@ -493,9 +505,9 @@ char *OpenDDLParser::parseIdentifier( char *in, char *end, Identifier **id ) {
// get size of id
size_t idLen( 0 );
char *start( in );
while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != '(' && *in != ')' ) {
in++;
idLen++;
while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] ) {
++in;
++idLen;
}
const size_t len( idLen );
@ -529,13 +541,13 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
}
bool ok( true );
if( *in == '[' ) {
if( *in == Grammar::OpenArrayToken[ 0 ] ) {
ok = false;
in++;
char *start( in );
while ( in != end ) {
in++;
if( *in == ']' ) {
if( *in == Grammar::CloseArrayToken[ 0 ] ) {
len = atoi( start );
ok = true;
in++;
@ -562,9 +574,9 @@ char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &na
if( nextName ) {
names.push_back( nextName );
}
while( ',' == *in ) {
while( Grammar::CommaSeparator[ 0 ] == *in ) {
in = getNextSeparator( in, end );
if( ',' == *in ) {
if( Grammar::CommaSeparator[ 0 ] == *in ) {
in = parseName( in, end, &nextName );
if( nextName ) {
names.push_back( nextName );
@ -846,7 +858,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value **data, size_t &n
}
in = getNextSeparator( in, end );
if( ',' != *in && '}' != *in && !isSpace( *in ) ) {
if( ',' != *in && Grammar::CloseBracketToken[ 0 ] != *in && !isSpace( *in ) ) {
break;
}
}

View File

@ -27,6 +27,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
BEGIN_ODDLPARSER_NS
static Value::Iterator end( ddl_nullptr );
Value::Iterator::Iterator()
: m_start( ddl_nullptr )
, m_current( ddl_nullptr ) {
@ -39,6 +41,12 @@ Value::Iterator::Iterator( Value *start )
// empty
}
Value::Iterator::Iterator( const Iterator &rhs )
: m_start( rhs.m_start )
, m_current( rhs.m_current ) {
// empty
}
Value::Iterator::~Iterator() {
// empty
}
@ -61,6 +69,38 @@ Value *Value::Iterator::getNext() {
return v;
}
const Value::Iterator Value::Iterator::operator++( int ) {
if( ddl_nullptr == m_current ) {
return end;
}
m_current = m_current->getNext();
Iterator inst( m_current );
return inst;
}
Value::Iterator &Value::Iterator::operator++( ) {
if( ddl_nullptr == m_current ) {
return end;
}
m_current = m_current->getNext();
return *this;
}
bool Value::Iterator::operator == ( const Iterator &rhs ) const {
return ( m_current == rhs.m_current );
}
Value *Value::Iterator::operator->( ) const {
if( nullptr == m_current ) {
return ddl_nullptr;
}
return m_current;
}
Value::Value( ValueType type )
: m_type( type )
, m_size( 0 )
@ -80,7 +120,8 @@ void Value::setBool( bool value ) {
bool Value::getBool() {
assert( ddl_bool == m_type );
return ( *m_data ) ? true : false;
return ( *m_data == 1 );
}
void Value::setInt8( int8 value ) {

View File

@ -101,6 +101,10 @@ public:
/// @return true, if a corresponding property is assigned to the node, false if not.
bool hasProperty( const std::string &name );
/// @brief Will return true, if any properties are assigned to the node instance.
/// @return True, if properties are assigned.
bool hasProperties() const;
/// @brief Search for a given property and returns it. Will return ddl_nullptr if no property was found.
/// @param name [in] The name for the property to look for.
/// @return The property or ddl_nullptr if no property was found.

View File

@ -56,10 +56,11 @@ BEGIN_ODDLPARSER_NS
// All C++11 constructs
# define ddl_nullptr nullptr
#else
// Fallback for older compilers
// Fall-back for older compilers
# define ddl_nullptr NULL
#endif // OPENDDL_NO_USE_CPP11
// Forward declarations
class DDLNode;
class Value;
@ -69,6 +70,7 @@ struct Reference;
struct Property;
struct DataArrayList;
// Platform-specific typedefs
#ifdef _WIN32
typedef signed __int64 int64_impl;
typedef unsigned __int64 uint64_impl;
@ -87,65 +89,36 @@ typedef unsigned short uint16; ///< Unsigned integer, 2 byte
typedef unsigned int uint32; ///< Unsigned integer, 4 byte
typedef uint64_impl uint64; ///< Unsigned integer, 8 byte
/// @brief Description of the type of a name.
enum NameType {
GlobalName, ///< Name is global.
LocalName ///< Name is local.
};
/// @brief Stores a text.
///
/// A text is stored in a simple character buffer. Texts buffer can be
/// greater than the number of stored characters in them.
struct DLL_ODDLPARSER_EXPORT Text {
size_t m_capacity; ///< The capacity of the text.
size_t m_len; ///< The length of the text.
char *m_buffer; ///< The buffer with the text.
/// @brief Stores a text
struct Text {
size_t m_capacity;
size_t m_len;
char *m_buffer;
/// @brief The constructor with a given text buffer.
/// @param buffer [in] The buffer.
/// @param numChars [in] The number of characters in the buffer.
Text( const char *buffer, size_t numChars );
Text( const char *buffer, size_t numChars )
: m_capacity( 0 )
, m_len( 0 )
, m_buffer( ddl_nullptr ) {
set( buffer, numChars );
}
/// @brief The destructor.
~Text();
~Text() {
clear();
}
/// @brief Clears the text.
void clear();
void clear() {
delete[] m_buffer;
m_buffer = ddl_nullptr;
m_capacity = 0;
m_len = 0;
}
/// @brief Set a new text.
/// @param buffer [in] The buffer.
/// @param numChars [in] The number of characters in the buffer.
void set( const char *buffer, size_t numChars );
void set( const char *buffer, size_t numChars ) {
clear();
if( numChars > 0 ) {
m_len = numChars;
m_capacity = m_len + 1;
m_buffer = new char[ m_capacity ];
strncpy( m_buffer, buffer, numChars );
m_buffer[ numChars ] = '\0';
}
}
/// @brief The compare operator for std::strings.
bool operator == ( const std::string &name ) const;
bool operator == ( const std::string &name ) const {
if( m_len != name.size() ) {
return false;
}
const int res( strncmp( m_buffer, name.c_str(), name.size() ) );
return ( 0 == res );
}
bool operator == ( const Text &rhs ) const {
if( m_len != rhs.m_len ) {
return false;
}
const int res( strncmp( m_buffer, rhs.m_buffer, m_len ) );
return ( 0 == res );
}
/// @brief The compare operator for Texts.
bool operator == ( const Text &rhs ) const;
private:
Text( const Text & );
@ -153,38 +126,48 @@ private:
};
/// @brief Stores an OpenDDL-specific identifier type.
struct Identifier {
Text m_text;
struct DLL_ODDLPARSER_EXPORT Identifier {
Text m_text; ///< The text element.
Identifier( char buffer[], size_t len )
: m_text( buffer, len ) {
// empty
}
/// @brief The constructor with a sized buffer full of characters.
/// @param buffer [in] The identifier buffer.
/// @param len [in] The length of the buffer
Identifier( const char buffer[], size_t len );
Identifier( char buffer[] )
: m_text( buffer, strlen( buffer ) ) {
// empty
}
/// @brief The constructor with a buffer full of characters.
/// @param buffer [in] The identifier buffer.
/// @remark Buffer must be null-terminated.
Identifier( const char buffer[] );
bool operator == ( const Identifier &rhs ) const {
return m_text == rhs.m_text;
}
/// @brief The destructor.
~Identifier();
/// @brief The compare operator.
bool operator == ( const Identifier &rhs ) const;
private:
Identifier( const Identifier & );
Identifier &operator = ( const Identifier & );
};
/// @brief Stores an OpenDDL-specific name
struct Name {
NameType m_type;
Identifier *m_id;
/// @brief Description of the type of a name.
enum NameType {
GlobalName, ///< Name is global.
LocalName ///< Name is local.
};
Name( NameType type, Identifier *id )
: m_type( type )
, m_id( id ) {
// empty
}
/// @brief Stores an OpenDDL-specific name
struct DLL_ODDLPARSER_EXPORT Name {
NameType m_type; ///< The type of the name ( @see NameType ).
Identifier *m_id; ///< The id.
/// @brief The constructor with the type and the id.
/// @param type [in] The name type.
/// @param id [in] The id.
Name( NameType type, Identifier *id );
/// @brief The destructor.
~Name();
private:
Name( const Name & );
@ -192,33 +175,20 @@ private:
};
/// @brief Stores a bundle of references.
struct Reference {
size_t m_numRefs;
Name **m_referencedName;
struct DLL_ODDLPARSER_EXPORT Reference {
size_t m_numRefs; ///< The number of stored references.
Name **m_referencedName; ///< The reference names.
Reference()
: m_numRefs( 0 )
, m_referencedName( ddl_nullptr ) {
// empty
}
/// @brief The default constructor.
Reference();
Reference( size_t numrefs, Name **names )
: m_numRefs( numrefs )
, m_referencedName( ddl_nullptr ) {
m_referencedName = new Name *[ numrefs ];
for( size_t i = 0; i < numrefs; i++ ) {
Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id );
m_referencedName[ i ] = name;
}
}
/// @brief The constructor with an array of ref names.
/// @param numrefs [in] The number of ref names.
/// @param names [in] The ref names.
Reference( size_t numrefs, Name **names );
~Reference() {
for( size_t i = 0; i < m_numRefs; i++ ) {
delete m_referencedName[ i ];
}
m_numRefs = 0;
m_referencedName = ddl_nullptr;
}
/// @brief The destructor.
~Reference();
private:
Reference( const Reference & );
@ -226,26 +196,21 @@ private:
};
/// @brief Stores a property list.
struct Property {
Identifier *m_key;
Value *m_value;
Reference *m_ref;
Property *m_next;
struct DLL_ODDLPARSER_EXPORT Property {
Identifier *m_key; ///< The identifier / key of the property.
Value *m_value; ///< The value assigned to its key / id ( ddl_nullptr if none ).
Reference *m_ref; ///< References assigned to its key / id ( ddl_nullptr if none ).
Property *m_next; ///< The next property ( ddl_nullptr if none ).
Property( Identifier *id )
: m_key( id )
, m_value( ddl_nullptr )
, m_ref( ddl_nullptr )
, m_next( ddl_nullptr ) {
// empty
}
/// @brief The default constructor.
Property();
~Property() {
m_key = ddl_nullptr;
m_value = ddl_nullptr;
m_ref = ddl_nullptr;;
m_next = ddl_nullptr;;
}
/// @brief The constructor for initialization.
/// @param id [in] The identifier
Property( Identifier *id );
/// @brief The destructor.
~Property();
private:
Property( const Property & );
@ -253,17 +218,16 @@ private:
};
/// @brief Stores a data array list.
struct DataArrayList {
size_t m_numItems;
Value *m_dataList;
DataArrayList *m_next;
struct DLL_ODDLPARSER_EXPORT DataArrayList {
size_t m_numItems; ///< The number of items in the list.
Value *m_dataList; ///< The data list ( ee Value ).
DataArrayList *m_next; ///< The next data array list ( ddl_nullptr if last ).
DataArrayList()
: m_numItems( 0 )
, m_dataList( ddl_nullptr )
, m_next( ddl_nullptr ) {
// empty
}
/// @brief The default constructor for initialization.
DataArrayList();
/// @brief The destructor.
~DataArrayList();
private:
DataArrayList( const DataArrayList & );
@ -271,17 +235,17 @@ private:
};
/// @brief Stores the context of a parsed OpenDDL declaration.
struct Context {
DDLNode *m_root;
struct DLL_ODDLPARSER_EXPORT Context {
DDLNode *m_root; ///< The root node of the OpenDDL node tree.
Context()
: m_root( ddl_nullptr ) {
// empty
}
/// @brief Constructor for initialization.
Context();
~Context() {
m_root = ddl_nullptr;
}
/// @brief Destructor.
~Context();
/// @brief Clears the whole node tree.
void clear();
private:
Context( const Context & );

View File

@ -39,6 +39,11 @@ struct Identifier;
struct Reference;
struct Property;
/// @brief Utility function to search for the next token or the end of the buffer.
/// @param in [in] The start position in the buffer.
/// @param end [in] The end position in the buffer.
/// @return Pointer showing to the next token or the end of the buffer.
/// @detail Will not increase buffer when already a valid buffer was found.
template<class T>
inline
T *lookForNextToken( T *in, T *end ) {
@ -48,13 +53,19 @@ T *lookForNextToken( T *in, T *end ) {
return in;
}
/// @brief Utility function to go for the next token or the end of the buffer.
/// @param in [in] The start position in the buffer.
/// @param end [in] The end position in the buffer.
/// @return Pointer showing to the next token or the end of the buffer.
/// @detail Will increase buffer by a minimum of one.
template<class T>
inline
T *getNextToken( T *in, T *end ) {
T *tmp( in );
while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
in = lookForNextToken( in, end );
/*while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
in++;
}
}*/
if( tmp == in ) {
in++;
}
@ -69,22 +80,76 @@ enum LogSeverity {
ddl_error_msg ///< Parser errors
};
//-------------------------------------------------------------------------------------------------
/// @class OpenDDLParser
/// @ingroup OpenDDLParser
///
/// @brief This is the main API for the OpenDDL-parser.
///
/// Use instances of this class to manage the parsing and handling of your parser contexts.
//-------------------------------------------------------------------------------------------------
class DLL_ODDLPARSER_EXPORT OpenDDLParser {
public:
/// @brief The log callback function pointer.
typedef void( *logCallback )( LogSeverity severity, const std::string &msg );
public:
/// @brief The default class constructor.
OpenDDLParser();
/// @brief The class constructor.
/// @param buffer [in] The buffer
/// @param len [in] Size of the buffer
OpenDDLParser( char *buffer, size_t len );
/// @brief The class destructor.
~OpenDDLParser();
/// @brief Setter for an own log callback function.
/// @param callback [in] The own callback.
void setLogCallback( logCallback callback );
/// @brief Getter for the log callback.
/// @return The current log callback.
logCallback getLogCallback() const;
/// @brief Assigns a new buffer to parse.
/// @param buffer [in] The buffer
/// @param len [in] Size of the buffer
void setBuffer( char *buffer, size_t len );
/// @brief Assigns a new buffer to parse.
/// @param buffer [in] The buffer as a std::vector.
void setBuffer( const std::vector<char> &buffer );
/// @brief Returns the buffer pointer.
/// @return The buffer pointer.
const char *getBuffer() const;
/// @brief Returns the size of the buffer.
/// @return The buffer size.
size_t getBufferSize() const;
/// @brief Clears all parser data, including buffer and active context.
void clear();
/// @brief Starts the parsing of the OpenDDL-file.
/// @return True in case of success, false in case of an error.
/// @remark In case of errors check log.
bool parse();
bool exportContext( Context *ctx, const std::string &filename );
/// @brief Returns the root node.
/// @return The root node.
DDLNode *getRoot() const;
/// @brief Returns the parser context, only available in case of a succeeded parsing.
/// @return Pointer to the active context or ddl_nullptr.
Context *getContext() const;
public: // parser helpers
char *parseNextNode( char *current, char *end );
char *parseHeader( char *in, char *end );
char *parseStructure( char *in, char *end );
@ -92,10 +157,6 @@ public:
void pushNode( DDLNode *node );
DDLNode *popNode();
DDLNode *top();
DDLNode *getRoot() const;
Context *getContext() const;
public: // static parser helpers
static void normalizeBuffer( std::vector<char> &buffer );
static char *parseName( char *in, char *end, Name **name );
static char *parseIdentifier( char *in, char *end, Identifier **id );

View File

@ -61,6 +61,8 @@ public:
/// @param start [in] The first value for iteration,
Iterator( Value *start );
Iterator( const Iterator &rhs );
/// @brief The class destructor.
~Iterator();
@ -72,12 +74,26 @@ public:
/// @return The next value, is ddl_nullptr in case of being the last item.
Value *getNext();
/// @brief The post-increment operator.
const Iterator operator++( int );
/// @brief The pre-increment operator.
Iterator &operator++( );
/// @brief The compare operator.
/// @param rhs [in] The instance to compare.
/// @return true if equal.
bool operator == ( const Iterator &rhs ) const;
/// @brief The * operator.
/// @return The instance or ddl_nullptr if end of list is reached.
Value *operator->( ) const;
private:
Value *m_start;
Value *m_current;
private:
Iterator( const Iterator & );
Iterator &operator = ( const Iterator & );
};

View File

@ -15,9 +15,9 @@ TEST(RemoveCommentsTest, testSingleLineComments)
"\ttrue) { // do something here \n"
"\t// hello ... and bye //\n";
char* szTest2 = new char[::strlen(szTest)+1];
::strcpy(szTest2,szTest);
const size_t len( ::strlen( szTest ) + 1 );
char* szTest2 = new char[ len ];
::strncpy( szTest2, szTest, len );
const char* szTestResult = "int i = 0; \n"
"if (4 == \n"
@ -45,8 +45,9 @@ TEST(RemoveCommentsTest, testMultiLineComments)
" "
" / * Incomplete comment */ */";
char* szTest2 = new char[::strlen(szTest)+1];
::strcpy(szTest2,szTest);
const size_t len( ::strlen( szTest ) + 1 );
char* szTest2 = new char[ len ];
::strncpy( szTest2, szTest, len );
CommentRemover::RemoveMultiLineComments("/*","*/",szTest2,' ');
EXPECT_STREQ(szTestResult, szTest2);