[Orxonox-commit 2622] r7327 - in code/branches/doc: doc/api src/libraries/util
landauf at orxonox.net
landauf at orxonox.net
Fri Sep 3 00:19:53 CEST 2010
Author: landauf
Date: 2010-09-03 00:19:53 +0200 (Fri, 03 Sep 2010)
New Revision: 7327
Removed:
code/branches/doc/doc/api/Groups.h
Modified:
code/branches/doc/src/libraries/util/Serialise.h
code/branches/doc/src/libraries/util/SharedPtr.cc
code/branches/doc/src/libraries/util/SharedPtr.h
code/branches/doc/src/libraries/util/SignalHandler.h
code/branches/doc/src/libraries/util/SmallObjectAllocator.cc
code/branches/doc/src/libraries/util/SmallObjectAllocator.h
code/branches/doc/src/libraries/util/StringUtils.cc
code/branches/doc/src/libraries/util/StringUtils.h
code/branches/doc/src/libraries/util/SubString.cc
code/branches/doc/src/libraries/util/SubString.h
code/branches/doc/src/libraries/util/TemplateUtils.h
code/branches/doc/src/libraries/util/VA_NARGS.h
Log:
added documentation
Deleted: code/branches/doc/doc/api/Groups.h
===================================================================
--- code/branches/doc/doc/api/Groups.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/doc/api/Groups.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -1,156 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-/**
- @defgroup Util Util
-
- The util library contains several functions, classes, and templates that can be used in different
- parts of the Orxonox-code. They provide functionalities for mathematical use, string manipulation,
- typeconversion, multi-types, error- and exception-handling, debug output, and many more.
-*/
-
-/**
- @defgroup Core Core
-
- The core library contains the framework of Orxonox - all important classes, functions, and macros
- that are used to create and manage classes and objects. Almost all classes in Orxonox need at least
- one of the core features.
-*/
-
-/**
- @defgroup Class Class management
- @ingroup Core
-*/
-
-/**
- @defgroup Object Object management
- @ingroup Core
-*/
-
-/**
- @defgroup Command Command
- @ingroup Core
-*/
-
-/**
- @defgroup Config Config
- @ingroup Core
-*/
-
-/**
- @defgroup Events Events
- @ingroup Core
-*/
-
-/**
- @defgroup Input Input
- @ingroup Core
-*/
-
-/**
- @defgroup Output Output
- @ingroup Core
-*/
-
-/**
- @defgroup XML XML
- @ingroup Core
-*/
-
-/**
- @defgroup Network Network
-
- The network library is used to connect clients and server, to synchronize objects and variables, and
- to transmit network function calls. It contains the central @ref orxonox::Server "Server" and
- @ref orxonox::Client "Client" classes as well as several functions and macros for
- @ref orxonox::Synchronisable "synchronisable" classes.
-*/
-
-/**
- @defgroup Tools Tools
-
- The tools are a bunch of utilities that belong to the Orxonox library, but are independent of other
- features.
-*/
-
-/**
- @defgroup Orxonox Orxonox
-
- The Orxonox library contains the central and most important classes of the game. Managers, interfaces,
- base-classes, and more are located in Orxonox. More specialized classes that inherit of the base-classes
- in Orxonox are often sourced out to the modules.
-*/
-
-/**
- @defgroup Modules Modules
-
- The modules are libraries that depend on the Orxonox library and that are loaded dynamically on runtime
- (in contrast to statically loaded libraries like util and core). Each module contains some classes that
- are usually connected to each other, but they are independent of other modules. However modules can still
- link to other modules, but only in a hierarchical order, no circular dependencies.
-*/
-
-/**
- @defgroup Designtools Designtools
- @ingroup Modules
-*/
-
-/**
- @defgroup Notifications Notifications
- @ingroup Modules
-*/
-
-/**
- @defgroup Objects Objects
- @ingroup Modules
-*/
-
-/**
- @defgroup Overlays Overlays
- @ingroup Modules
-*/
-
-/**
- @defgroup Pickup Pickup
- @ingroup Modules
-*/
-
-/**
- @defgroup Pong Pong
- @ingroup Modules
-*/
-
-/**
- @defgroup Questsystem Questsystem
- @ingroup Modules
-*/
-
-/**
- @defgroup Weapons Weapons
- @ingroup Modules
-*/
Modified: code/branches/doc/src/libraries/util/Serialise.h
===================================================================
--- code/branches/doc/src/libraries/util/Serialise.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/Serialise.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -28,6 +28,7 @@
/**
@file
+ @ingroup Util
@brief Functions to serialise most of the types/classed used in Orxonox
*/
@@ -52,20 +53,20 @@
/** @brief checks whether the variable of type T is the same as in the bytestream */
template <class T> inline bool checkEquality( const T& variable, uint8_t* mem );
-
+
// =========== char*
-
+
inline uint32_t returnSize( char*& variable )
{
return strlen(variable)+1;
}
-
+
inline void saveAndIncrease( char*& variable, uint8_t*& mem )
{
strcpy((char*)mem, variable);
mem += returnSize(variable);
}
-
+
inline void loadAndIncrease( char*& variable, uint8_t*& mem )
{
if( variable )
@@ -75,12 +76,12 @@
strcpy((char*)variable, (char*)mem);
mem += len;
}
-
+
inline bool checkEquality( char*& variable, uint8_t* mem )
{
return strcmp(variable, (char*)mem)==0;
}
-
+
// =================== Template specialisation stuff =============
// =========== bool
@@ -422,7 +423,7 @@
double temp = static_cast<double>(variable);
return memcmp(&temp, mem, sizeof(uint64_t))==0;
}
-
+
// =========== string
template <> inline uint32_t returnSize( const std::string& variable )
Modified: code/branches/doc/src/libraries/util/SharedPtr.cc
===================================================================
--- code/branches/doc/src/libraries/util/SharedPtr.cc 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SharedPtr.cc 2010-09-02 22:19:53 UTC (rev 7327)
@@ -26,13 +26,21 @@
*
*/
+/**
+ @file
+ @brief Static linkage of the SmallObjectAllocator used by SharedPtr.
+*/
+
#include "SharedPtr.h"
namespace orxonox
{
- SmallObjectAllocator& createSharedCounterPool()
+ namespace detail
{
- static SmallObjectAllocator instance(sizeof(SharedCounterImpl<void>));
- return instance;
+ SmallObjectAllocator& createSharedCounterPool()
+ {
+ static SmallObjectAllocator instance(sizeof(SharedCounterImpl<void>));
+ return instance;
+ }
}
}
Modified: code/branches/doc/src/libraries/util/SharedPtr.h
===================================================================
--- code/branches/doc/src/libraries/util/SharedPtr.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SharedPtr.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -26,6 +26,123 @@
*
*/
+/**
+ @defgroup SharedPtr SharedPtr<T>
+ @ingroup Util Object
+*/
+
+/**
+ @file
+ @ingroup Util SharedPtr
+ @brief Definition of the SharedPtr template that is used to manage pointers.
+
+ @anchor SharedPtrExample
+
+ The orxonox::SharedPtr template can be used to manage a pointer to an object
+ that was created with new. The SharedPtr acts like the pointer itself, but it
+ keeps track of the number of references to it. If all references are removed,
+ SharedPtr deletes the managed object automatically.
+
+ Example:
+
+ Classic implementation using new and delete:
+ @code
+ void someFunction()
+ {
+ MyClass* object = new MyClass(); // Create a new instance of MyClass
+
+ object->myFunction(); // Calls MyClass::myFunction()
+
+ delete object; // Delete the object at the end of the scope
+ }
+ @endcode
+
+ The same function using SharedPtr:
+ @code
+ void someFunction()
+ {
+ SharedPtr<MyClass> object = new MyClass(); // Create a new instance of MyClass and store its pointer in a SharedPtr
+
+ object->myFunction(); // Calls MyClass::myFunction()
+
+ } // At the end of the scope, the SharedPtr is destroyed. Because no other SharedPtrs
+ // point at the object, the object itself is also destroyed automatically
+ @endcode
+
+ This is especially handy if you do not know what will happen with an object that was
+ created with new, for example if you pass it to another object. If multiple instances
+ share a pointer to the same object, none of these instances can delete the object
+ without interfering with the other instances. But if none of the instances destroy the
+ object, it will never be destroyed and results in a memory leak. With a SharedPtr
+ however you don't have to think about destroying the object, because the SharedPtr
+ itself keeps track of the references.
+
+ Example:
+
+ Classic implementation using new and delete:
+ @code
+ class OtherClass // Declaration of some class
+ {
+ public:
+ OtherClass(MyClass* object) // Constructor
+ {
+ this->object_ = object; // Assigns the pointer to the member variable object_
+ }
+
+ ~OtherClass() // Destructor
+ {
+ ??? // What to do with object_?
+ }
+
+ private:
+ MyClass* object_; // A pointer to the object
+ };
+
+ void someFunction()
+ {
+ MyClass* object = new MyClass(); // Create a new instance of MyClass
+
+ OtherClass* other1 = new OtherClass(object); // Create an instance of OtherClass and pass the object pointer
+ OtherClass* other2 = new OtherClass(object); // "
+ OtherClass* other3 = new OtherClass(object); // "
+
+ ??? // What happens with object now?
+ }
+ @endcode
+
+ If you use SharedPtr<MyClass> instead of a classic MyClass* pointer, the instance of
+ MyClass would be automatically destroyed if all instances of OtherClass are destroyed.
+ You don't need any code in the destructor and you can completely forget about the
+ object, because its managed by the SharedPtr.
+
+ The same code using SharedPtr:
+ @code
+ class OtherClass // Declaration of some class
+ {
+ public:
+ OtherClass(const SharedPtr<MyClass>& object) // Constructor
+ {
+ this->object_ = object; // Assigns the pointer to the member variable object_
+ }
+
+ private:
+ SharedPtr<MyClass> object_; // A SharedPtr to the object
+ };
+
+ void someFunction()
+ {
+ SharedPtr<MyClass> object = new MyClass(); // Create a new instance of MyClass
+
+ OtherClass* other1 = new OtherClass(object); // Create an instance of OtherClass and pass the object pointer
+ OtherClass* other2 = new OtherClass(object); // "
+ OtherClass* other3 = new OtherClass(object); // "
+
+ } // The SmartPtr "object" is destroyed at the end of the scope,
+ // but the three instances of OtherClass keep the object alive
+ // until they are all destroyed.
+ @endcode
+*/
+
#ifndef _SharedPtr_H__
#define _SharedPtr_H__
@@ -38,38 +155,57 @@
namespace orxonox
{
- class SharedCounter
+ namespace detail
{
- public:
- SharedCounter() : count_(1) {}
- virtual void destroy() = 0;
+ /// BaseClass of SharedCounterImpl, has a counter that is initialized with 1
+ class SharedCounter
+ {
+ public:
+ SharedCounter() : count_(1) {}
+ virtual void destroy() = 0;
- int count_;
- };
+ int count_;
+ };
- template <class T>
- class SharedCounterImpl : public SharedCounter
- {
- public:
- SharedCounterImpl(T* pointer) : pointer_(pointer) {}
+ /// Child class of SharedCounter, keeps a pointer to an object of type T that can be destroyed with destroy()
+ template <class T>
+ class SharedCounterImpl : public SharedCounter
+ {
+ public:
+ SharedCounterImpl(T* pointer) : pointer_(pointer) {}
- void destroy()
- {
- delete this->pointer_;
- }
+ void destroy()
+ {
+ delete this->pointer_;
+ }
- private:
- T* pointer_;
- };
+ private:
+ T* pointer_;
+ };
- _UtilExport SmallObjectAllocator& createSharedCounterPool();
+ _UtilExport SmallObjectAllocator& createSharedCounterPool();
- FORCEINLINE SmallObjectAllocator& getSharedCounterPool()
- {
- static SmallObjectAllocator& instance = createSharedCounterPool();
- return instance;
+ FORCEINLINE SmallObjectAllocator& getSharedCounterPool()
+ {
+ static SmallObjectAllocator& instance = createSharedCounterPool();
+ return instance;
+ }
}
+ /**
+ @brief The SharedPtr template is a utility to manage pointers to an object.
+ @param T The type of the managed object
+
+ SharedPtr acts like a real pointer, except that it keeps track of the number of
+ references to the object. If the the number of references drops to zero, the
+ object is destroyed automatically.
+
+ @see See @ref SharedPtrExample "this description" for some examples and more information.
+
+ @note The number of references is stored in a separate object that is shared
+ among all instances of SharedPtr that point to the same pointer. This object is
+ also responsible for destroying the pointer if the reference counter becomes zero.
+ */
template <class T>
class SharedPtr
{
@@ -77,25 +213,29 @@
friend class SharedPtr;
public:
+ /// Default constructor, the pointer is set to NULL.
inline SharedPtr() : pointer_(0), counter_(0)
{
}
+ /// Constructor, creates a SharedPtr that points to @a pointer, increments the counter.
inline SharedPtr(T* pointer) : pointer_(pointer), counter_(0)
{
if (this->pointer_)
{
- void* chunk = getSharedCounterPool().alloc();
- this->counter_ = new (chunk) SharedCounterImpl<T>(this->pointer_);
+ void* chunk = detail::getSharedCounterPool().alloc();
+ this->counter_ = new (chunk) detail::SharedCounterImpl<T>(this->pointer_);
}
}
+ /// Copy-constructor, this SharedPtr now points to the same object like the other SharedPtr, increments the counter.
inline SharedPtr(const SharedPtr& other) : pointer_(other.pointer_), counter_(other.counter_)
{
if (this->pointer_)
++this->counter_->count_;
}
+ /// Copy-constructor for SharedPtr with another template agument, increments the counter.
template <class O>
inline SharedPtr(const SharedPtr<O>& other) : pointer_(other.pointer_), counter_(other.counter_)
{
@@ -103,6 +243,7 @@
++this->counter_->count_;
}
+ /// Destructor, decrements the counter and deletes the object if the counter becomes zero.
inline ~SharedPtr()
{
if (this->pointer_)
@@ -112,17 +253,19 @@
if (this->counter_->count_ == 0)
{
this->counter_->destroy();
- getSharedCounterPool().free(this->counter_);
+ detail::getSharedCounterPool().free(this->counter_);
}
}
}
+ /// Assigns a new object, decrements the counter of the old object, increments the counter of the new object.
inline SharedPtr& operator=(const SharedPtr& other)
{
SharedPtr(other).swap(*this);
return *this;
}
+ /// Assigns a new object with another template argument, decrements the counter of the old object, increments the counter of the new object.
template <class O>
inline SharedPtr& operator=(const SharedPtr<O>& other)
{
@@ -130,6 +273,7 @@
return *this;
}
+ /// Casts the pointer to another type
template <class O>
inline SharedPtr<O> cast() const
{
@@ -137,28 +281,33 @@
return SharedPtr<O>(temp, this->counter_);
}
+ /// Overloaded -> operator, returns the pointer to the managed object.
inline T* operator->() const
{
assert(this->pointer_ != 0);
return this->pointer_;
}
+ /// Overloaded * operator, returns a reference ot the managed object.
inline T& operator*() const
{
assert(this->pointer_ != 0);
return *this->pointer_;
}
+ /// Returns the pointer to the managed object.
inline T* get() const
{
return this->pointer_;
}
+ /// Returns true if the pointer is not NULL.
inline operator bool() const
{
return (this->pointer_ != 0);
}
+ /// Swaps the pointer and the counter of two instances of SharedPtr with the same template argument.
inline void swap(SharedPtr& other)
{
std::swap(this->pointer_, other.pointer_);
@@ -166,16 +315,48 @@
}
private:
- inline SharedPtr(T* pointer, SharedCounter* counter) : pointer_(pointer), counter_(counter)
+ /// Private constructor, used by the cast() function.
+ inline SharedPtr(T* pointer, detail::SharedCounter* counter) : pointer_(pointer), counter_(counter)
{
if (this->pointer_)
++this->counter_->count_;
}
- T* pointer_;
- SharedCounter* counter_;
+ T* pointer_; ///< A pointer to the managed object of type @a T
+ detail::SharedCounter* counter_; ///< A pointer to the shared reference counter
};
+ /**
+ @brief A child class of SharedPtr, used to reflect the hierarchy of the underlying class @a T.
+ @param T The type of the managed object
+ @param Parent The type of the SharedPtr that manages the parent class of @a T
+
+ This class is used to reflect the hierarchy of the underlying class @a T.
+ For example the @c Functor classes: While a @c Functor* pointer would be managed by
+ @c SharedPtr<Functor>, the child class @c FunctorStatic is managed by the class
+ <tt>SharedChildPtr<FunctorStatic, SharedPtr<Functor> ></tt>.
+
+ The second template argument @a Parent is used as the parent class of
+ SharedChildPtr. This means that each instance of <tt>SharedChildPtr<T, Parent></tt>
+ can be upcasted to @c Parent.
+
+ So for example this works:
+ @code
+ SharedChildPtr<FunctorStatic, SharedPtr<Functor> > functorStatic = createFunctor(&MyClass::myStaticFunction);
+ SharedPtr<Functor> functor = functorStatic;
+ @endcode
+
+ @note There are some typedefs and more to make the usage of SharedChildPtr easier
+ for the classes Functor and Executor. See FunctorPtr.h and ExecutorPtr.h. The above
+ example could thus be simplified the following way:
+ @code
+ FunctorStaticPtr functorStatic = createFunctor(&MyClass::myStaticFunction);
+ FunctorPtr functor = functorStatic;
+ @endcode
+
+ @see See SharedPtr for more information about the base class SharedPtr.
+ @see See @ref SharedPtrExample "this description" for some examples about how to use SharedPtr.
+ */
template <class T, class Parent>
class SharedChildPtr : public Parent
{
Modified: code/branches/doc/src/libraries/util/SignalHandler.h
===================================================================
--- code/branches/doc/src/libraries/util/SignalHandler.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SignalHandler.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -28,6 +28,7 @@
/**
@file
+ @ingroup Util
@brief Declaration of the SignalHandler class.
*/
@@ -67,6 +68,7 @@
typedef std::list<SignalRec> SignalRecList;
typedef std::list<SignalCallbackRec> SignalCallbackList;
+ /// The SignalHandler is used to catch signals like SIGSEGV and write a backtrace to the logfile.
class SignalHandler : public Singleton<SignalHandler>
{
friend class Singleton<SignalHandler>;
@@ -98,6 +100,7 @@
namespace orxonox
{
+ /// The SignalHandler is used to catch signals like SIGSEGV and write a backtrace to the logfile. Not implemented on Windows.
class _UtilExport SignalHandler : public Singleton<SignalHandler>
{
friend class Singleton<SignalHandler>;
Modified: code/branches/doc/src/libraries/util/SmallObjectAllocator.cc
===================================================================
--- code/branches/doc/src/libraries/util/SmallObjectAllocator.cc 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SmallObjectAllocator.cc 2010-09-02 22:19:53 UTC (rev 7327)
@@ -26,61 +26,96 @@
*
*/
+/**
+ @file
+ @brief Implementation of SmallObjectAllocator
+*/
+
#include "SmallObjectAllocator.h"
namespace orxonox
{
+ /**
+ @brief Constructor: initializes the allocator and its values.
+ @param objectSize The size in bytes (returned by sizeof()) of the allocated objects
+ @param numObjects The number of objects that are allocated in one block of memory
+ */
SmallObjectAllocator::SmallObjectAllocator(size_t objectSize, size_t numObjects)
{
- this->objectSize_ = std::max(objectSize, sizeof(Chunk));
- this->numObjects_ = numObjects;
+ this->chunkSize_ = std::max(objectSize, sizeof(Chunk)); // the chunk's size will be the maximum of the object's size and the size of a Chunk object itself
+ this->numChunksPerBlock_ = numObjects;
this->first_ = 0;
}
+ /**
+ @brief Destructor: deletes the allocated memory blocks.
+ */
SmallObjectAllocator::~SmallObjectAllocator()
{
for (std::vector<char*>::iterator it = this->blocks_.begin(); it != this->blocks_.end(); ++it)
delete[] *it;
}
+ /**
+ @brief Helper function, used to set the next_ pointer of a Chunk.
+ */
/* static */ void SmallObjectAllocator::setNext(void* chunk, void* next)
{
static_cast<Chunk*>(chunk)->next_ = static_cast<Chunk*>(next);
}
+ /**
+ @brief Helper function, returns the next_ pointer of a Chunk
+ */
/* static */ void* SmallObjectAllocator::getNext(void* chunk)
{
return static_cast<Chunk*>(chunk)->next_;
}
+ /**
+ @brief Returns the first free memory chunk or allocates a new block of memory.
+ */
void* SmallObjectAllocator::alloc()
{
+ // get the first free chunk
void* chunk = this->first_;
+ // check if the chunk exists
if (chunk)
{
+ // yes it does - the first_ pointer now points to the second element in the list
this->first_ = getNext(chunk);
}
else
{
- char* block = new char[this->objectSize_ * this->numObjects_];
+ // no it doesnt - allocate a new block of memory
+ char* block = new char[this->chunkSize_ * this->numChunksPerBlock_];
this->blocks_.push_back(block);
- for (size_t i = 1; i < this->numObjects_ - 1; ++i)
- setNext(block + i * this->objectSize_, block + (i + 1) * this->objectSize_);
+ // iterate through the chunks in the new memory block and link them together to a single linked list
+ for (size_t i = 1; i < this->numChunksPerBlock_ - 1; ++i)
+ setNext(block + i * this->chunkSize_, block + (i + 1) * this->chunkSize_);
- setNext(block + (this->numObjects_ - 1) * this->objectSize_, 0);
+ // the next_ pointer of the last chunk must point to NULL
+ setNext(block + (this->numChunksPerBlock_ - 1) * this->chunkSize_, 0);
- this->first_ = block + this->objectSize_;
+ // The second chunk in the block is assigned to the first_ pointer
+ this->first_ = block + this->chunkSize_;
+ // The first chunk in the block is returned
chunk = block;
}
+ // return the pointer to the chunk
return chunk;
}
+ /**
+ @brief Puts the memory chunk back on the list of free memory.
+ */
void SmallObjectAllocator::free(void* chunk)
{
+ // The first_ pointer points to the freed chunk, its next_ pointer points to the rest of the list
setNext(chunk, this->first_);
this->first_ = chunk;
}
Modified: code/branches/doc/src/libraries/util/SmallObjectAllocator.h
===================================================================
--- code/branches/doc/src/libraries/util/SmallObjectAllocator.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SmallObjectAllocator.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -26,6 +26,51 @@
*
*/
+/**
+ @defgroup SmallObjectAllocator SmallObjectAllocator
+ @ingroup Util Object
+*/
+
+/**
+ @file
+ @ingroup Util SmallObjectAllocator
+ @brief Declaration of SmallObjectAllocator
+
+ @anchor SmallObjectAllocatorExample
+
+ The default implementations of new and delete are designed to work with objects of
+ arbitrary size. They are thus not optimal for small objects.
+ @ref orxonox::SmallObjectAllocator "SmallObjectAllocator" allocates a large memory
+ block and divides it into small chunks. These chunks are returned by the function
+ @ref orxonox::SmallObjectAllocator::alloc() "alloc()" and can be used to create a
+ new object using the placement new operator. Instead of delete, the function
+ @ref orxonox::SmallObjectAllocator::free() "free()" is used to give the memory
+ back to SmallObjectAllocator.
+
+ Example:
+ @code
+ SmallObjectAllocator allocator(sizeof(MySmallObject)); // Create an allocator. The size of the memory chunks must equal the size of the desired class
+
+ void* chunk = allocator.alloc(); // Allocate a memory chunk
+ MySmallObject* object = new (chunk) MySmallObject(); // Call the placement new operator
+
+ object->someFunction(); // Do something with the object
+
+ object->~MySmallObject(); // Call the destructor
+ allocator.free(object); // Free the allocated memory
+ @endcode
+
+ @b Important: You have to call the destructor of the object manually, because this
+ is not automatically done by the allocator nor free().
+
+ @note The destructor can be ignored if it is empty or not implemented. This saves
+ another amount of time.
+
+ @remarks For a distributed usage of SmallObjectAllocator it may be a good idea to
+ create a static function that returns an instance to it. The allocator then works
+ like a singleton and can be accesses from everywhere.
+*/
+
#ifndef _SmallObjectAllocator_H__
#define _SmallObjectAllocator_H__
@@ -34,11 +79,19 @@
namespace orxonox
{
+ /**
+ @brief This class is used to allocate and free small objects (usually not polymorphic).
+
+ SmallObjectAllocator provides a fast alternative to new and delete for small objects.
+
+ @see See @ref SmallObjectAllocatorExample "this description" for more information and an example.
+ */
class _UtilExport SmallObjectAllocator
{
+ /// The memory chunk is at the same time an element of a single linked list.
struct Chunk
{
- Chunk* next_;
+ Chunk* next_; ///< A pointer to the next chunk in the list
};
public:
@@ -52,11 +105,11 @@
static void setNext(void* chunk, void* next);
static void* getNext(void* chunk);
- void* first_;
- size_t objectSize_;
- size_t numObjects_;
+ void* first_; ///< A pointer to the first free memory chunk
+ size_t chunkSize_; ///< The size of each chunk (and usually also the size of the created objects)
+ size_t numChunksPerBlock_; ///< The number of chunks per memory block
- std::vector<char*> blocks_;
+ std::vector<char*> blocks_; ///< A list of all allocated memory blocks (used to destroy them again)
};
}
Modified: code/branches/doc/src/libraries/util/StringUtils.cc
===================================================================
--- code/branches/doc/src/libraries/util/StringUtils.cc 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/StringUtils.cc 2010-09-02 22:19:53 UTC (rev 7327)
@@ -40,17 +40,16 @@
namespace orxonox
{
+ /// A blank string (""). Used to return a blank string by reference.
std::string BLANKSTRING;
+ /// Returns a string of a unique number. This function is guaranteed to never return the same string twice.
std::string getUniqueNumberString()
{
return multi_cast<std::string>(getUniqueNumber());
}
- /**
- @brief Removes all whitespaces from a string.
- @param str The string to strip
- */
+ /// Removes all whitespaces from a string.
void strip(std::string* str)
{
size_t pos;
@@ -62,11 +61,7 @@
str->erase(pos, 1);
}
- /**
- @brief Returns a copy of a string without whitespaces.
- @param str The string to strip
- @return The stripped line
- */
+ /// Returns a copy of a string without whitespaces.
std::string getStripped(const std::string& str)
{
std::string output(str);
@@ -74,11 +69,7 @@
return output;
}
- /**
- @brief Returns a copy of a string without trailing whitespaces.
- @param str The string
- @return The modified copy
- */
+ /// Returns a copy of a string without trailing whitespaces.
std::string removeTrailingWhitespaces(const std::string& str)
{
size_t pos1 = 0;
@@ -89,10 +80,10 @@
}
/**
- @brief Returns the position of the next quote in the string, starting with start.
+ @brief Returns the position of the next quotation mark in the string, starting with start.
@param str The string
- @param start The startposition
- @return The position of the next quote (std::string::npos if there is no next quote)
+ @param start The first position to look at
+ @return The position of the next quotation mark (@c std::string::npos if there is none)
*/
size_t getNextQuote(const std::string& str, size_t start)
{
@@ -114,10 +105,10 @@
}
/**
- @brief Returns true if pos is between two quotes.
+ @brief Returns true if pos is between two quotation marks.
@param str The string
@param pos The position to check
- @return True if pos is between two quotes
+ @return True if pos is between two quotation marks
*/
bool isBetweenQuotes(const std::string& str, size_t pos)
{
@@ -139,11 +130,7 @@
return ((quotecount % 2) == 1);
}
- /**
- @brief Returns true if the string contains something like '..."between quotes"...'.
- @param str The string
- @return True if there is something between quotes
- */
+ /// Returns true if the string contains something like '..."between quotaton marks"...'.
bool hasStringBetweenQuotes(const std::string& str)
{
size_t pos1 = getNextQuote(str, 0);
@@ -151,10 +138,7 @@
return (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1);
}
- /**
- @brief If the string contains something like '..."between quotes"...' then 'between quotes' gets returned (without quotes).
- @param str The string between the quotes
- */
+ /// If the string contains something like '..."between quotaton marks"...' then 'between quotaton marks' gets returned, otherwise "".
std::string getStringBetweenQuotes(const std::string& str)
{
size_t pos1 = getNextQuote(str, 0);
@@ -166,9 +150,8 @@
}
/**
- @brief Removes enclosing quotes if available (including whitespaces at the outside of the quotes).
- @param str The string to strip
- @return The string with removed quotes
+ @brief Removes enclosing quotation marks if available (including whitespaces at the outside of the quotation marks).
+ @return The striped string without quotation marks
*/
std::string stripEnclosingQuotes(const std::string& str)
{
@@ -206,9 +189,8 @@
}
/**
- @brief Removes enclosing {braces} (braces must be exactly on the beginning and the end of the string).
- @param str The string to strip
- @return The striped string
+ @brief Removes enclosing braces '{' and '}' (the braces must be exactly on the beginning and the end of the string).
+ @return The striped string without braces
*/
std::string stripEnclosingBraces(const std::string& str)
{
@@ -222,8 +204,6 @@
/**
@brief Determines if a string is a comment (starts with a comment-symbol).
- @param str The string to check
- @return True = it's a comment
A comment is defined by a leading '#', '%', ';' or '//'.
*/
@@ -251,21 +231,13 @@
return false;
}
- /**
- @brief Determines if a string is empty (contains only whitespaces).
- @param str The string to check
- @return True = it's empty
- */
+ /// Determines if a string is empty (contains only whitespaces).
bool isEmpty(const std::string& str)
{
return getStripped(str).empty();
}
- /**
- @brief Determines if a string contains only numbers and maximal one '.'.
- @param str The string to check
- @return True = it's a number
- */
+ /// Determines if a string contains only numbers and maximal one '.'.
bool isNumeric(const std::string& str)
{
bool foundPoint = false;
@@ -286,8 +258,14 @@
/**
@brief Adds backslashes to the given string which makes special chars visible. Existing slashes will be doubled.
- @param str The string to manipulate
- @return The string with added slashes
+
+ This function converts all special chars like line breaks, tabs, quotation marks etc. into
+ a human readable format by adding a backslash. So for example "\n" will be converted to
+ "\\" + "n".
+
+ This is usually used when a string is written to a file.
+
+ @see removeSlashes
*/
std::string addSlashes(const std::string& str)
{
@@ -318,8 +296,13 @@
/**
@brief Removes backslashes from the given string. Double backslashes are interpreted as one backslash.
- @param str The string to manipulate
- @return The string with removed slashes
+
+ This function removes all backslashes and converts the human readable equivalents of
+ special chars like "\\" + "n" into their real meaning (in this case a line break or "\n").
+
+ This is usually used when reading a string from a file.
+
+ @see addSlashes
*/
std::string removeSlashes(const std::string& str)
{
@@ -359,10 +342,7 @@
return output;
}
- /**
- @brief Replaces each char between A and Z with its lowercase equivalent.
- @param str The string to convert
- */
+ /// Replaces each char between A and Z with its lowercase equivalent.
void lowercase(std::string* str)
{
for (size_t i = 0; i < str->size(); ++i)
@@ -371,11 +351,7 @@
}
}
- /**
- @brief Returns a copy of the given string without uppercase chars.
- @param str The string
- @return The copy
- */
+ /// Returns a copy of the given string where all chars are converted to lowercase.
std::string getLowercase(const std::string& str)
{
std::string output(str);
@@ -383,10 +359,7 @@
return output;
}
- /**
- @brief Replaces each char between a and z with its uppercase equivalent.
- @param str The string to convert
- */
+ /// Replaces each char between a and z with its uppercase equivalent.
void uppercase(std::string* str)
{
for (size_t i = 0; i < str->size(); ++i)
@@ -395,11 +368,7 @@
}
}
- /**
- @brief Returns a copy of the given string without lowercase chars.
- @param str The string
- @return The copy
- */
+ /// Returns a copy of the given string where all chars are converted to uppercase.
std::string getUppercase(const std::string& str)
{
std::string output(str);
@@ -409,8 +378,7 @@
/**
@brief Compares two strings ignoring different casing.
- @param s1 First string
- @param s2 Second string
+ @return s1 == s1 -> returns 0 / s1 < s2 -> returns -1 / s1 >= s2 -> returns 1
*/
int nocaseCmp(const std::string& s1, const std::string& s2)
{
@@ -436,7 +404,7 @@
/**
- @brief Compares the first 'len' chars of two strings ignoring different casing.
+ @brief Compares the first @a len chars of two strings ignoring different casing.
@param s1 First string
@param s2 Second string
@param len Maximal number of chars to compare
@@ -461,41 +429,28 @@
return 0;
}
- /**
- @brief Returns true if the string contains a comment, introduced by #, %, ; or //.
- @param str The string
- @return True if the string contains a comment
- */
+ /// Returns true if the string contains a comment, introduced by #, %, ; or //.
bool hasComment(const std::string& str)
{
return (getCommentPosition(str) != std::string::npos);
}
- /**
- @brief If the string contains a comment, the comment gets returned (including the comment symbol), an empty string otherwise.
- @param str The string
- @return The comment
- */
+ /// If the string contains a comment, the comment gets returned (including the comment symbol), an empty string otherwise.
std::string getComment(const std::string& str)
{
return str.substr(getCommentPosition(str));
}
- /**
- @brief If the string contains a comment, the position of the comment-symbol gets returned, std::string::npos otherwise.
- @param str The string
- @return The position
- */
+ /// If the string contains a comment, the position of the comment-symbol gets returned, @c std::string::npos otherwise.
size_t getCommentPosition(const std::string& str)
{
return getNextCommentPosition(str, 0);
}
/**
- @brief Returns the position of the next comment-symbol, starting with start.
+ @brief Returns the position of the next comment-symbol, starting with @a start.
@param str The string
- @param start The startposition
- @return The position
+ @param start The first position to look at
*/
size_t getNextCommentPosition(const std::string& str, size_t start)
{
Modified: code/branches/doc/src/libraries/util/StringUtils.h
===================================================================
--- code/branches/doc/src/libraries/util/StringUtils.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/StringUtils.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -27,7 +27,13 @@
*/
/**
+ @defgroup String String functions
+ @ingroup Util
+*/
+
+/**
@file
+ @ingroup Util String
@brief Declaration of several string manipulation functions, used in many parts of the game.
*/
Modified: code/branches/doc/src/libraries/util/SubString.cc
===================================================================
--- code/branches/doc/src/libraries/util/SubString.cc 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SubString.cc 2010-09-02 22:19:53 UTC (rev 7327)
@@ -39,317 +39,256 @@
#include "SubString.h"
#include <cstdio>
+#include "Debug.h"
namespace orxonox
{
- /**
- * @brief default constructor
- */
- SubString::SubString()
- {}
+ const std::string SubString::WhiteSpaces = " \n\t";
+ const std::string SubString::WhiteSpacesWithComma = " \n\t,";
+ const SubString SubString::NullSubString = SubString();
-
/**
- * @brief create a SubString from
- * @param string the String to Split
- * @param delimiter the Character at which to split string (delimiter)
- */
- SubString::SubString(const std::string& string, char delimiter)
+ @brief Default constructor.
+ */
+ SubString::SubString()
{
- this->split(string, delimiter);
}
-
/**
- * @brief Splits a string into multiple tokens.
- * @param string The string to split
- * @param delimiters Multiple set of characters at what to split. (delimiters)
- * @param delimiterNeighbours Neighbours of the delimiters that will be erased as well.
- * @param emptyEntries If empty entries are added to the list of SubStrings
- * @param escapeChar The escape character that overrides splitters commends and so on...
- * @param removeEscapeChar If true, the escape char is removed from the tokens
- * @param safemode_char Within these characters splitting won't happen
- * @param removeSafemodeChar Removes the safemode_char from the beginning and the ending of a token
- * @param openparenthesis_char The beginning of a safemode is marked with this
- * @param closeparenthesis_char The ending of a safemode is marked with this
- * @param removeParenthesisChars Removes the parenthesis from the beginning and the ending of a token
- * @param comment_char The comment character.
- */
- SubString::SubString(const std::string& string,
- const std::string& delimiters, const std::string& delimiterNeighbours, bool emptyEntries,
- char escapeChar, bool removeEscapeChar, char safemode_char, bool removeSafemodeChar,
- char openparenthesis_char, char closeparenthesis_char, bool removeParenthesisChars, char comment_char)
+ @brief Splits a string into multiple tokens.
+ @param line The line to split
+ @param delimiters Multiple characters at which to split the line
+ @param delimiterNeighbours Neighbours of the delimiters that will be erased as well (for example white-spaces)
+ @param bAllowEmptyEntries If true, empty tokens are also added to the SubString (if there are two delimiters without a char in between)
+ @param escapeChar The escape character that is used to escape safemode chars (for example if you want to use a quotation mark between two other quotation marks).
+ @param bRemoveEscapeChar If true, the escape char is removed from the tokens
+ @param safemodeChar Within these characters splitting won't happen (usually the quotation marks)
+ @param bRemoveSafemodeChar Removes the safemodeChar from the beginning and the ending of a token
+ @param openparenthesisChar The beginning of a safemode is marked with this (usually an opening brace)
+ @param closeparenthesisChar The ending of a safemode is marked with this (usually a closing brace)
+ @param bRemoveParenthesisChars Removes the parenthesis chars from the beginning and the ending of a token
+ @param commentChar The comment character (used to ignore the part of the line after the comment char).
+ */
+ SubString::SubString(const std::string& line,
+ const std::string& delimiters, const std::string& delimiterNeighbours, bool bAllowEmptyEntries,
+ char escapeChar, bool bRemoveEscapeChar, char safemodeChar, bool bRemoveSafemodeChar,
+ char openparenthesisChar, char closeparenthesisChar, bool bRemoveParenthesisChars, char commentChar)
{
- SubString::splitLine(this->strings, this->bInSafemode, string, delimiters, delimiterNeighbours, emptyEntries, escapeChar, removeEscapeChar, safemode_char, removeSafemodeChar, openparenthesis_char, closeparenthesis_char, removeParenthesisChars, comment_char);
+ SubString::splitLine(this->tokens_, this->bTokenInSafemode_, line, delimiters, delimiterNeighbours, bAllowEmptyEntries, escapeChar, bRemoveEscapeChar, safemodeChar, bRemoveSafemodeChar, openparenthesisChar, closeparenthesisChar, bRemoveParenthesisChars, commentChar);
}
/**
- * @brief creates a SubSet of a SubString.
- * @param subString the SubString to take a set from.
- * @param subSetBegin the beginning to the end
- */
- SubString::SubString(const SubString& subString, unsigned int subSetBegin)
+ @brief creates a new SubString based on a subset of an other SubString.
+ @param other The other SubString
+ @param begin The beginning of the subset
+
+ The subset ranges from the token with index @a begin to the end of the tokens.
+ If @a begin is greater than the greatest index, the new SubString will be empty.
+ */
+ SubString::SubString(const SubString& other, unsigned int begin)
{
- for (unsigned int i = subSetBegin; i < subString.size(); i++)
+ for (unsigned int i = begin; i < other.size(); ++i)
{
- this->strings.push_back(subString[i]);
- this->bInSafemode.push_back(subString.isInSafemode(i));
+ this->tokens_.push_back(other[i]);
+ this->bTokenInSafemode_.push_back(other.isInSafemode(i));
}
}
-
/**
- * @brief creates a SubSet of a SubString.
- * @param subString the SubString to take a Set from
- * @param subSetBegin the beginning to the end
- * @param subSetEnd the end of the SubSet (max subString.size() will be checked internaly)
- */
- SubString::SubString(const SubString& subString, unsigned int subSetBegin, unsigned int subSetEnd)
+ @brief creates a new SubString based on a subset of an other SubString.
+ @param other The other SubString
+ @param begin The beginning of the subset
+ @param end The end of the subset
+
+ The subset ranges from the token with index @a begin until (but not including) the token with index @a end.
+ If @a begin or @a end are beyond the allowed index, the resulting SubString will be empty.
+ */
+ SubString::SubString(const SubString& other, unsigned int begin, unsigned int end)
{
- for (unsigned int i = subSetBegin; i < subString.size() && i < subSetEnd; i++)
+ for (unsigned int i = begin; i < std::min(other.size(), end); ++i)
{
- this->strings.push_back(subString[i]);
- this->bInSafemode.push_back(subString.isInSafemode(i));
+ this->tokens_.push_back(other[i]);
+ this->bTokenInSafemode_.push_back(other.isInSafemode(i));
}
}
/**
- * @brief creates a Substring from a count and values set.
- * @param argc: the Arguments Count.
- * @param argv: Argument Values.
- */
+ @brief Creates a SubString from a count and values set.
+ @param argc The number of arguments
+ @param argv An array of pointers to the arguments
+ */
SubString::SubString(unsigned int argc, const char** argv)
{
for(unsigned int i = 0; i < argc; ++i)
{
- this->strings.push_back(std::string(argv[i]));
- this->bInSafemode.push_back(false);
+ this->tokens_.push_back(std::string(argv[i]));
+ this->bTokenInSafemode_.push_back(false);
}
}
/**
- * @brief removes the object from memory
- */
+ @brief Destructor
+ */
SubString::~SubString()
{ }
- /** @brief An empty String */
- // const std::string SubString::emptyString = "";
- /** @brief Helper that gets you a String consisting of all White Spaces */
- const std::string SubString::WhiteSpaces = " \n\t";
- /** @brief Helper that gets you a String consisting of all WhiteSpaces and the Comma */
- const std::string SubString::WhiteSpacesWithComma = " \n\t,";
- /** An Empty SubString */
- const SubString SubString::NullSubString = SubString();
-
/**
- * @brief stores the Value of subString in this SubString
- * @param subString will be copied into this String.
- * @returns this SubString.
- */
- SubString& SubString::operator=(const SubString& subString)
+ @brief Stores the tokens of @a other in this SubString
+ @return This SubString.
+ */
+ SubString& SubString::operator=(const SubString& other)
{
- this->strings = subString.strings;
- this->bInSafemode = subString.bInSafemode;
+ this->tokens_ = other.tokens_;
+ this->bTokenInSafemode_ = other.bTokenInSafemode_;
return *this;
}
-
/**
- * @brief comparator.
- * @param subString the SubString to compare against this one.
- * @returns true if the Stored Strings match
- */
- bool SubString::operator==(const SubString& subString) const
+ @brief Compares this SubString to another SubString and returns true if they contain the same values.
+ */
+ bool SubString::operator==(const SubString& other) const
{
- return ((this->strings == subString.strings) && (this->bInSafemode == subString.bInSafemode));
+ return ((this->tokens_ == other.tokens_) && (this->bTokenInSafemode_ == other.bTokenInSafemode_));
}
/**
- * @brief comparator.
- * @param subString the SubString to compare against this one.
- * @returns true if the Stored Strings match
- */
- bool SubString::compare(const SubString& subString) const
+ @copydoc operator==
+ */
+ bool SubString::compare(const SubString& other) const
{
- return (*this == subString);
+ return (*this == other);
}
/**
- * @brief comparator.
- * @param subString the SubString to compare against this one.
- * @param length how many entries to compare. (from 0 to length)
- * @returns true if the Stored Strings match
- */
- bool SubString::compare(const SubString& subString, unsigned int length) const
+ @brief Compares this SubString to another SubString and returns true if the first @a length values match.
+ @param other The other SubString
+ @param length How many tokens to compare
+ */
+ bool SubString::compare(const SubString& other, unsigned int length) const
{
- if (length > this->size() || length > subString.size())
+ if (length > this->size() || length > other.size())
return false;
- for (unsigned int i = 0; i < length; i++)
- if ((this->strings[i] != subString.strings[i]) || (this->bInSafemode[i] != subString.bInSafemode[i]))
+ for (unsigned int i = 0; i < length; ++i)
+ if ((this->tokens_[i] != other.tokens_[i]) || (this->bTokenInSafemode_[i] != other.bTokenInSafemode_[i]))
return false;
return true;
}
-
/**
- * @brief append operator
- * @param subString the String to append.
- * @returns a SubString where this and subString are appended.
- */
- SubString SubString::operator+(const SubString& subString) const
+ @brief Concatenates the tokens of two SubStrings and returns the resulting new SubString
+ @return A new SubString that contains the tokens of this and the other SubString
+ */
+ SubString SubString::operator+(const SubString& other) const
{
- return SubString(*this) += subString;
+ return SubString(*this) += other;
}
-
/**
- * @brief append operator.
- * @param subString append subString to this SubString.
- * @returns this substring appended with subString
- */
- SubString& SubString::operator+=(const SubString& subString)
+ @brief Appends the tokens of @a other to this SubString
+ @return This SubString
+ */
+ SubString& SubString::operator+=(const SubString& other)
{
- for (unsigned int i = 0; i < subString.size(); i++)
+ for (unsigned int i = 0; i < other.size(); ++i)
{
- this->strings.push_back(subString[i]);
- this->bInSafemode.push_back(subString.isInSafemode(i));
+ this->tokens_.push_back(other[i]);
+ this->bTokenInSafemode_.push_back(other.isInSafemode(i));
}
return *this;
}
-
/**
- * @brief Split the String at
- * @param string where to split
- * @param splitter delimiter.
- */
- unsigned int SubString::split(const std::string& string, char splitter)
+ @copydoc SubString(const std::string&,const std::string&,const std::string&,bool,char,bool,char,bool,char,char,bool,char)
+ */
+ unsigned int SubString::split(const std::string& line,
+ const std::string& delimiters, const std::string& delimiterNeighbours, bool bAllowEmptyEntries,
+ char escapeChar, bool bRemoveEscapeChar, char safemodeChar, bool bRemoveSafemodeChar,
+ char openparenthesisChar, char closeparenthesisChar, bool bRemoveParenthesisChars, char commentChar)
{
- this->strings.clear();
- this->bInSafemode.clear();
- char split[2];
- split[0] = splitter;
- split[1] = '\0';
- SubString::splitLine(this->strings, this->bInSafemode, string, split);
- return strings.size();
+ this->tokens_.clear();
+ this->bTokenInSafemode_.clear();
+ SubString::splitLine(this->tokens_, this->bTokenInSafemode_, line, delimiters, delimiterNeighbours, bAllowEmptyEntries, escapeChar, bRemoveEscapeChar, safemodeChar, bRemoveSafemodeChar, openparenthesisChar, closeparenthesisChar, bRemoveParenthesisChars, commentChar);
+ return this->tokens_.size();
}
-
/**
- * @brief Splits a string into multiple tokens.
- * @param string The string to split
- * @param delimiters Multiple set of characters at what to split. (delimiters)
- * @param delimiterNeighbours: Neighbours of the delimiters that will be erased too.
- * @param emptyEntries: If empty entries are added to the list of SubStrings
- * @param escapeChar The escape character that overrides splitters commends and so on...
- * @param removeEscapeChar If true, the escape char is removed from the tokens
- * @param safemode_char Within these characters splitting won't happen
- * @param removeSafemodeChar Removes the safemode_char from the beginning and the ending of a token
- * @param openparenthesis_char The beginning of a safemode is marked with this
- * @param closeparenthesis_char The ending of a safemode is marked with this
- * @param removeParenthesisChars Removes the parenthesis from the beginning and the ending of a token
- * @param comment_char The comment character.
- */
- unsigned int SubString::split(const std::string& string,
- const std::string& delimiters, const std::string& delimiterNeighbours, bool emptyEntries,
- char escapeChar, bool removeEscapeChar, char safemode_char, bool removeSafemodeChar,
- char openparenthesis_char, char closeparenthesis_char, bool removeParenthesisChars, char comment_char)
- {
- this->strings.clear();
- this->bInSafemode.clear();
- SubString::splitLine(this->strings, this->bInSafemode, string, delimiters, delimiterNeighbours, emptyEntries, escapeChar, removeEscapeChar, safemode_char, removeSafemodeChar, openparenthesis_char, closeparenthesis_char, removeParenthesisChars, comment_char);
- return this->strings.size();
- }
-
-
- /**
- * @brief joins together all Strings of this Substring.
- * @param delimiter the String between the subStrings.
- * @returns the joined String.
- */
+ @brief Joins the tokens of this SubString using the given delimiter and returns a string.
+ @param delimiter This delimiter will be placed between each two tokens
+ @return The joined string.
+ */
std::string SubString::join(const std::string& delimiter) const
{
- if (!this->strings.empty())
+ if (!this->tokens_.empty())
{
- std::string retVal = this->strings[0];
- for (unsigned int i = 1; i < this->strings.size(); i++)
- retVal += delimiter + this->strings[i];
+ std::string retVal = this->tokens_[0];
+ for (unsigned int i = 1; i < this->tokens_.size(); ++i)
+ retVal += delimiter + this->tokens_[i];
return retVal;
}
else
return "";
}
-
/**
- * @brief creates a SubSet of a SubString.
- * @param subSetBegin the beginning to the end
- * @returns the SubSet
- *
- * This function is added for your convenience, and does the same as
- * SubString::SubString(const SubString& subString, unsigned int subSetBegin)
- */
- SubString SubString::subSet(unsigned int subSetBegin) const
+ @brief Creates a subset of this SubString.
+ @param begin The beginning of the subset
+ @return A new SubString containing the defined subset.
+
+ The subset ranges from the token with index @a begin to the end of the tokens.
+ If @a begin is greater than the greatest index, the new SubString will be empty.
+
+ This function is added for your convenience, and does the same as
+ SubString::SubString(const SubString& other, unsigned int begin)
+ */
+ SubString SubString::subSet(unsigned int begin) const
{
- return SubString(*this, subSetBegin);
+ return SubString(*this, begin);
}
-
/**
- * @brief creates a SubSet of a SubString.
- * @param subSetBegin the beginning to
- * @param subSetEnd the end of the SubSet to select (if bigger than subString.size() it will be downset.)
- * @returns the SubSet
- *
- * This function is added for your convenience, and does the same as
- * SubString::SubString(const SubString& subString, unsigned int subSetBegin)
- */
- SubString SubString::subSet(unsigned int subSetBegin, unsigned int subSetEnd) const
+ @brief Creates a subset of this SubString.
+ @param begin The beginning of the subset
+ @param end The ending of the subset
+ @return A new SubString containing the defined subset.
+
+ The subset ranges from the token with index @a begin until (but not including) the token with index @a end.
+ If @a begin or @a end are beyond the allowed index, the resulting SubString will be empty.
+
+ This function is added for your convenience, and does the same as
+ SubString::SubString(const SubString& other, unsigned int begin, unsigned int end)
+ */
+ SubString SubString::subSet(unsigned int begin, unsigned int end) const
{
- return SubString(*this, subSetBegin, subSetEnd);
+ return SubString(*this, begin, end);
}
-
/**
- * @brief Splits a line into tokens and stores them in ret.
- * @param ret The array, where the splitted strings will be stored in
- * @param bInSafemode A vector wich stores for each character of the string if it is in safemode or not
- * @param line The inputLine to split
- * @param delimiters A string of delimiters (here the input will be splitted)
- * @param delimiterNeighbours Neighbours of the delimiter, that will be removed if they are to the left or the right of a delimiter.
- * @param emptyEntries If empty strings are added to the list of strings.
- * @param escape_char Escape carater (escapes splitters)
- * @param removeEscapeChar If true, the escape char is removed from the tokens
- * @param safemode_char The beginning of the safemode is marked with this
- * @param removeSafemodeChar Removes the safemode_char from the beginning and the ending of a token
- * @param openparenthesis_char The beginning of a safemode is marked with this
- * @param closeparenthesis_char The ending of a safemode is marked with this
- * @param removeParenthesisChars Removes the parenthesis from the beginning and the ending of a token
- * @param comment_char The beginning of a comment is marked with this: (until the end of a line)
- * @param start_state The initial state on how to parse the string.
- * @return SPLIT_LINE_STATE the parser was in when returning
- *
- * This is the Actual Splitting Algorithm from Clemens Wacha
- * Supports delimiters, escape characters,
- * ignores special characters between safemode_char and between comment_char and linend '\n'.
- */
+ @copydoc SubString(const std::string&,const std::string&,const std::string&,bool,char,bool,char,bool,char,char,bool,char)
+ @param tokens The array, where the splitted strings will be stored in
+ @param bTokenInSafemode A vector wich stores for each character of the string if it is in safemode or not
+ @param start_state The internal state of the parser
+
+ This is the actual splitting algorithm from Clemens Wacha.
+ Supports delimiters, escape characters, ignores special characters between safemodeChar and between commentChar and line end "\n".
+
+ Extended by Orxonox to support parenthesis as additional safe-mode.
+ */
SubString::SPLIT_LINE_STATE
- SubString::splitLine(std::vector<std::string>& ret,
- std::vector<bool>& bInSafemode,
+ SubString::splitLine(std::vector<std::string>& tokens,
+ std::vector<bool>& bTokenInSafemode,
const std::string& line,
const std::string& delimiters,
const std::string& delimiterNeighbours,
- bool emptyEntries,
- char escape_char,
- bool removeEscapeChar,
- char safemode_char,
- bool removeSafemodeChar,
- char openparenthesis_char,
- char closeparenthesis_char,
- bool removeParenthesisChars,
- char comment_char,
+ bool bAllowEmptyEntries,
+ char escapeChar,
+ bool bRemoveEscapeChar,
+ char safemodeChar,
+ bool bRemoveSafemodeChar,
+ char openparenthesisChar,
+ char closeparenthesisChar,
+ bool bRemoveParenthesisChars,
+ char commentChar,
SPLIT_LINE_STATE start_state)
{
SPLIT_LINE_STATE state = start_state;
@@ -359,15 +298,15 @@
std::string token;
bool inSafemode = false;
- if(start_state != SL_NORMAL && ret.size() > 0)
+ if(start_state != SL_NORMAL && tokens.size() > 0)
{
- token = ret[ret.size()-1];
- ret.pop_back();
+ token = tokens[tokens.size()-1];
+ tokens.pop_back();
}
- if(start_state != SL_NORMAL && bInSafemode.size() > 0)
+ if(start_state != SL_NORMAL && bTokenInSafemode.size() > 0)
{
- inSafemode = bInSafemode[bInSafemode.size()-1];
- bInSafemode.pop_back();
+ inSafemode = bTokenInSafemode[bTokenInSafemode.size()-1];
+ bTokenInSafemode.pop_back();
}
while(i < line.size())
@@ -375,36 +314,36 @@
switch(state)
{
case SL_NORMAL:
- if(line[i] == escape_char)
+ if(line[i] == escapeChar)
{
state = SL_ESCAPE;
- if (!removeEscapeChar)
+ if (!bRemoveEscapeChar)
token += line[i];
}
- else if(line[i] == safemode_char)
+ else if(line[i] == safemodeChar)
{
state = SL_SAFEMODE;
inSafemode = true;
- if (!removeSafemodeChar)
+ if (!bRemoveSafemodeChar)
token += line[i];
}
- else if(line[i] == openparenthesis_char)
+ else if(line[i] == openparenthesisChar)
{
state = SL_PARENTHESES;
inSafemode = true;
- if (!removeParenthesisChars)
+ if (!bRemoveParenthesisChars)
token += line[i];
}
- else if(line[i] == comment_char)
+ else if(line[i] == commentChar)
{
if (fallBackNeighbours > 0)
token = token.substr(0, token.size() - fallBackNeighbours);
- /// FINISH
- if(emptyEntries || token.size() > 0)
+ // FINISH
+ if(bAllowEmptyEntries || token.size() > 0)
{
- ret.push_back(token);
+ tokens.push_back(token);
token.clear();
- bInSafemode.push_back(inSafemode);
+ bTokenInSafemode.push_back(inSafemode);
inSafemode = false;
}
token += line[i]; // EAT
@@ -415,12 +354,12 @@
// line[i] is a delimiter
if (fallBackNeighbours > 0)
token = token.substr(0, token.size() - fallBackNeighbours);
- /// FINISH
- if(emptyEntries || token.size() > 0)
+ // FINISH
+ if(bAllowEmptyEntries || token.size() > 0)
{
- ret.push_back(token);
+ tokens.push_back(token);
token.clear();
- bInSafemode.push_back(inSafemode);
+ bTokenInSafemode.push_back(inSafemode);
inSafemode = false;
}
state = SL_NORMAL;
@@ -433,7 +372,7 @@
++fallBackNeighbours;
else
{
- i++;
+ ++i;
continue;
}
}
@@ -443,7 +382,7 @@
}
break;
case SL_ESCAPE:
- if (!removeSafemodeChar)
+ if (!bRemoveSafemodeChar)
token += line[i];
else
{
@@ -460,13 +399,13 @@
state = SL_NORMAL;
break;
case SL_SAFEMODE:
- if(line[i] == safemode_char)
+ if(line[i] == safemodeChar)
{
state = SL_NORMAL;
- if (!removeSafemodeChar)
+ if (!bRemoveSafemodeChar)
token += line[i];
}
- else if(line[i] == escape_char)
+ else if(line[i] == escapeChar)
{
state = SL_SAFEESCAPE;
}
@@ -490,13 +429,13 @@
break;
case SL_PARENTHESES:
- if(line[i] == closeparenthesis_char)
+ if(line[i] == closeparenthesisChar)
{
state = SL_NORMAL;
- if (!removeParenthesisChars)
+ if (!bRemoveParenthesisChars)
token += line[i];
}
- else if(line[i] == escape_char)
+ else if(line[i] == escapeChar)
{
state = SL_PARENTHESESESCAPE;
}
@@ -522,12 +461,12 @@
case SL_COMMENT:
if(line[i] == '\n')
{
- /// FINISH
+ // FINISH
if(token.size() > 0)
{
- ret.push_back(token);
+ tokens.push_back(token);
token.clear();
- bInSafemode.push_back(inSafemode);
+ bTokenInSafemode.push_back(inSafemode);
inSafemode = false;
}
state = SL_NORMAL;
@@ -542,31 +481,30 @@
// nothing
break;
}
- i++;
+ ++i;
}
- /// FINISH
+ // FINISH
if (fallBackNeighbours > 0)
token = token.substr(0, token.size() - fallBackNeighbours);
- if(emptyEntries || token.size() > 0)
+ if(bAllowEmptyEntries || token.size() > 0)
{
- ret.push_back(token);
+ tokens.push_back(token);
token.clear();
- bInSafemode.push_back(inSafemode);
+ bTokenInSafemode.push_back(inSafemode);
inSafemode = false;
}
return(state);
}
-
/**
- * @brief Some nice debug information about this SubString
- */
+ @brief Some nice debug information about this SubString.
+ */
void SubString::debug() const
{
- printf("Substring-information::count=%d ::", this->strings.size());
- for (unsigned int i = 0; i < this->strings.size(); i++)
- printf("s%d='%s'::", i, this->strings[i].c_str());
- printf("\n");
+ COUT(0) << "Substring-information::count=" << this->tokens_.size() << " ::";
+ for (unsigned int i = 0; i < this->tokens_.size(); ++i)
+ COUT(0) << "s" << i << "='" << this->tokens_[i].c_str() << "'::";
+ COUT(0) << std::endl;
}
}
Modified: code/branches/doc/src/libraries/util/SubString.h
===================================================================
--- code/branches/doc/src/libraries/util/SubString.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/SubString.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -36,25 +36,50 @@
* Extended by Fabian 'x3n' Landau by the SL_PARENTHESES mode.
*/
- /*!
- * @file
- * @brief a small class to get the parts of a string separated by commas
- *
- * This class is also identified as a Tokenizer. It splits up one long
- * String into multiple small ones by a designated Delimiter.
- *
- * Substring is Advanced, and it is possible, to split a string by ','
- * but also removing leading and trailing spaces around the comma.
- *
- * Example:
- * Split the String std::string st = "1345, The new empire , is , orxonox"
- * is splitted with:
- * @code SubString(st, ',', " \n\t") @endcode
- * into
- * "1345", "The new empire", "is", "orxonox"
- * As you can see, the useless spaces around ',' were removed.
- */
+ /**
+ @file
+ @ingroup Util String
+ @brief a small class to get the parts of a string separated by commas
+ @anchor SubStringExample
+
+ The class SubString can be used to split an std::string into multiple tokens, using
+ a delimiter. SubString allows different options, for example to remove whitespaces
+ around the delimiters or different safe-mode chars, like quotation marks and braces.
+
+ You can access the tokens of the SubString using the [] operator like an array.
+ SubString also supports to join the tokens (or a subset of the tokens) again using
+ @ref orxonox::SubString::join() "join()". It's even possible to get a subset of the
+ SubString as another SubString using @ref orxonox::SubString::subSet() "subSet()".
+
+ Example:
+ @code
+ std::string text = "This is a test, \"Hello \\\" World\" and vector {1, 2, 3}";
+ SubString tokens(text, SubString::WhiteSpaces, "", false, '\\', true, '"', true, '{', '}', true, '\0');
+
+ for (unsigned int i = 0; i < tokens.size(); ++i)
+ COUT(0) << i << ": " << tokens[i] << std::endl;
+ @endcode
+
+ The output of this code is:
+ - 0: This
+ - 1: is
+ - 2: a
+ - 3: test,
+ - 4: Hello " World
+ - 5: and
+ - 6: vector
+ - 7: 1, 2, 3
+
+ The string was split using the delimiter " ". A string between quotation mark is not
+ split, the same holds for strings between '{' and '}'. Note how the quotation marks and
+ the braces were removed from the tokens, because the corresponding argument is 'true'.
+
+ Also note that the comma after "test" in token 3 is still there - it is neither part of the
+ delimiters SubString::WhiteSpaces nor part of the delimiterNeighbours parameter, so it
+ remains a part of the token.
+*/
+
#ifndef __SubString_H__
#define __SubString_H__
@@ -65,111 +90,126 @@
namespace orxonox
{
- //! A class that can load one string and split it in multipe ones
/**
- * SubString is a very Powerfull way to create a SubSet from a String
- * It can be used, to Split strings append them and join them again.
- */
+ @brief A class that splits a string into multiple tokens using different options.
+
+ The string is split into multiple tokens using a delimiter. Different options like
+ escape character, quotation marks, and more can be used to satisfy your needs.
+
+ See @ref SubStringExample "this description" for an example.
+ */
class _UtilExport SubString
{
- public:
- //! An enumerator for the State the Parser is in
- typedef enum {
+ /// An enumerator for the internal state of the parser
+ enum SPLIT_LINE_STATE
+ {
SL_NORMAL, //!< Normal state
SL_ESCAPE, //!< After an escape character
- SL_SAFEMODE, //!< In safe mode (between "" mostly).
+ SL_SAFEMODE, //!< In safe mode (usually between quotation marks).
SL_SAFEESCAPE, //!< In safe mode with the internal escape character, that escapes even the savemode character.
SL_COMMENT, //!< In Comment mode.
SL_PARENTHESES, //!< Between parentheses (usually '{' and '}')
SL_PARENTHESESESCAPE, //!< Between parentheses with the internal escape character, that escapes even the closing paranthesis character.
- } SPLIT_LINE_STATE;
+ };
-
public:
SubString();
- SubString(const std::string& string, char delimiter = ',');
- SubString(const std::string& string,
- const std::string& delimiters, const std::string& delimiterNeighbours = "", bool emptyEntries=false,
- char escapeChar ='\\', bool removeEscapeChar = true, char safemode_char = '"', bool removeSafemodeChar = true,
- char openparenthesis_char = '{', char closeparenthesis_char = '}', bool removeParenthesisChars = true, char comment_char = '\0');
+ SubString(const std::string& line,
+ const std::string& delimiters = SubString::WhiteSpaces,
+ const std::string& delimiterNeighbours = "",
+ bool bAllowEmptyEntries=false,
+ char escapeChar ='\\',
+ bool bRemoveEscapeChar = true,
+ char safemodeChar = '"',
+ bool bRemoveSafemodeChar = true,
+ char openparenthesisChar = '{',
+ char closeparenthesisChar = '}',
+ bool bRemoveParenthesisChars = true,
+ char commentChar = '\0');
SubString(unsigned int argc, const char** argv);
- /** @brief create a Substring as a copy of another one. @param subString the SubString to copy. */
- SubString(const SubString& subString) { *this = subString; };
- SubString(const SubString& subString, unsigned int subSetBegin);
- SubString(const SubString& subString, unsigned int subSetBegin, unsigned int subSetEnd);
+ SubString(const SubString& other, unsigned int begin);
+ SubString(const SubString& other, unsigned int begin, unsigned int end);
~SubString();
// operate on the SubString
- SubString& operator=(const SubString& subString);
- bool operator==(const SubString& subString) const;
- bool compare(const SubString& subString) const;
- bool compare(const SubString& subString, unsigned int length) const;
- SubString operator+(const SubString& subString) const;
- SubString& operator+=(const SubString& subString);
- /** @param subString the String to append @returns appended String. @brief added for convenience */
- SubString& append(const SubString subString) { return (*this += subString); };
+ SubString& operator=(const SubString& other);
+ bool operator==(const SubString& other) const;
+ bool compare(const SubString& other) const;
+ bool compare(const SubString& other, unsigned int length) const;
+ SubString operator+(const SubString& other) const;
+ SubString& operator+=(const SubString& other);
+ /// Appends the tokens of another SubString to this. @return This SubString.
+ inline SubString& append(const SubString& other) { return (*this += other); }
/////////////////////////////////////////
// Split and Join the any String. ///////
- unsigned int split(const std::string& string = "", char delimiter = ',');
- unsigned int split(const std::string& string,
- const std::string& delimiters, const std::string& delimiterNeighbours = "", bool emptyEntries = false,
- char escapeChar ='\\', bool removeEscapeChar = true, char safemode_char = '"', bool removeSafemodeChar = true,
- char openparenthesis_char = '{', char closeparenthesis_char = '}', bool removeParenthesisChars = true, char comment_char = '\0');
+ unsigned int split(const std::string& line,
+ const std::string& delimiters = SubString::WhiteSpaces,
+ const std::string& delimiterNeighbours = "",
+ bool bAllowEmptyEntries = false,
+ char escapeChar ='\\',
+ bool bRemoveEscapeChar = true,
+ char safemodeChar = '"',
+ bool bRemoveSafemodeChar = true,
+ char openparenthesisChar = '{',
+ char closeparenthesisChar = '}',
+ bool bRemoveParenthesisChars = true,
+ char commentChar = '\0');
+
std::string join(const std::string& delimiter = " ") const;
////////////////////////////////////////
// retrieve a SubSet from the String
- SubString subSet(unsigned int subSetBegin) const;
- SubString subSet(unsigned int subSetBegin, unsigned int subSetEnd) const;
+ SubString subSet(unsigned int begin) const;
+ SubString subSet(unsigned int begin, unsigned int end) const;
// retrieve Information from within
- /** @brief Returns true if the SubString is empty */
- inline bool empty() const { return this->strings.empty(); };
- /** @brief Returns the count of Strings stored in this substring */
- inline unsigned int size() const { return this->strings.size(); };
- /** @brief Returns the i'th string from the subset of Strings @param i the i'th String */
- inline const std::string& operator[](unsigned int i) const { return this->strings[i]; };
- /** @brief Returns the i'th string from the subset of Strings @param i the i'th String */
- inline const std::string& getString(unsigned int i) const { return (*this)[i]; };
- /** @brief Returns all Strings as std::vector */
- inline const std::vector<std::string>& getAllStrings() const { return this->strings; }
- /** @brief Returns true if the token is in safemode. @param i the i'th token */
- inline bool isInSafemode(unsigned int i) const { return this->bInSafemode[i]; }
- /** @brief Returns the front of the StringList. */
- inline const std::string& front() const { return this->strings.front(); };
- /** @brief Returns the back of the StringList. */
- inline const std::string& back() const { return this->strings.back(); };
- /** @brief removes the back of the strings list. */
- inline void pop_back() { this->strings.pop_back(); this->bInSafemode.pop_back(); };
+ /// Returns true if the SubString is empty
+ inline bool empty() const { return this->tokens_.empty(); }
+ /// Returns the number of tokens stored in this SubString
+ inline unsigned int size() const { return this->tokens_.size(); }
+ /// Returns the i'th token from the subset of strings @param index The index of the requested doken
+ inline const std::string& operator[](unsigned int index) const { return this->tokens_[index]; }
+ /// Returns the i'th token from the subset of strings @param index The index of the requested token
+ inline const std::string& getString(unsigned int index) const { return (*this)[index]; }
+ /// Returns all tokens as std::vector
+ inline const std::vector<std::string>& getAllStrings() const { return this->tokens_; }
+ /// Returns true if the token is in safemode. @param index The index of the token
+ inline bool isInSafemode(unsigned int index) const { return this->bTokenInSafemode_[index]; }
+ /// Returns the front of the list of tokens.
+ inline const std::string& front() const { return this->tokens_.front(); }
+ /// Returns the back of the list of tokens.
+ inline const std::string& back() const { return this->tokens_.back(); }
+ /// Removes the back of the list of tokens.
+ inline void pop_back() { this->tokens_.pop_back(); this->bTokenInSafemode_.pop_back(); }
+ void debug() const;
+
+ public:
+ static const std::string WhiteSpaces; ///< All whitespaces (usually used as delimiters or delimiterNeighbours
+ static const std::string WhiteSpacesWithComma; ///< All whitespaces and the comma (usually used as delimiters)
+ static const SubString NullSubString; ///< An empty SubString
+
+ private:
// the almighty algorithm.
- static SPLIT_LINE_STATE splitLine(std::vector<std::string>& ret,
- std::vector<bool>& bInSafemode,
+ static SPLIT_LINE_STATE splitLine(std::vector<std::string>& tokens,
+ std::vector<bool>& bTokenInSafemode,
const std::string& line,
const std::string& delimiters = SubString::WhiteSpaces,
const std::string& delimiterNeighbours = "",
- bool emptyEntries = false,
- char escape_char = '\\',
- bool removeEscapeChar = true,
- char safemode_char = '"',
- bool removeSafemodeChar = true,
- char openparenthesis_char = '{',
- char closeparenthesis_char = '}',
- bool removeParenthesisChars = true,
- char comment_char = '\0',
+ bool bAllowEmptyEntries = false,
+ char escapeChar = '\\',
+ bool bRemoveEscapeChar = true,
+ char safemodeChar = '"',
+ bool bRemoveSafemodeChar = true,
+ char openparenthesisChar = '{',
+ char closeparenthesisChar = '}',
+ bool bRemoveParenthesisChars = true,
+ char commentChar = '\0',
SPLIT_LINE_STATE start_state = SL_NORMAL);
- // debugging.
- void debug() const;
- public:
- static const std::string WhiteSpaces;
- static const std::string WhiteSpacesWithComma;
- static const SubString NullSubString;
-
- private:
- std::vector<std::string> strings; //!< strings produced from a single string splitted in multiple strings
- std::vector<bool> bInSafemode;
+ std::vector<std::string> tokens_; ///< The tokens after spliting the input line
+ std::vector<bool> bTokenInSafemode_; ///< Saves for each token if it was in safe mode (between quotation marks or parenthesis)
};
}
Modified: code/branches/doc/src/libraries/util/TemplateUtils.h
===================================================================
--- code/branches/doc/src/libraries/util/TemplateUtils.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/TemplateUtils.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -28,6 +28,7 @@
/**
@file
+ @ingroup Util
@brief Declaration of various helper templates.
*/
Modified: code/branches/doc/src/libraries/util/VA_NARGS.h
===================================================================
--- code/branches/doc/src/libraries/util/VA_NARGS.h 2010-09-02 10:08:16 UTC (rev 7326)
+++ code/branches/doc/src/libraries/util/VA_NARGS.h 2010-09-02 22:19:53 UTC (rev 7327)
@@ -28,6 +28,7 @@
/**
@file
+ @ingroup Util
@brief Declaration of the ORXONOX_VA_NARGS macro which returns the number of arguments passed to a variadic macro.
*/
More information about the Orxonox-commit
mailing list