00001 #ifndef __TYPELIB_TYPEMODEL_HH__
00002 #define __TYPELIB_TYPEMODEL_HH__
00003
00004 #include <string>
00005 #include <list>
00006 #include <map>
00007 #include <set>
00008 #include <vector>
00009 #include <stdint.h>
00010 #include <stdexcept>
00011
00012 namespace Typelib
00013 {
00014 struct OutputStream;
00015 struct InputStream;
00016
00017 class Registry;
00018
00020 class Type
00021 {
00022 public:
00023
00024 enum Category
00025 {
00026 NullType = 0,
00027 Array ,
00028 Pointer,
00029 Numeric,
00030 Enum ,
00031 Compound,
00032 Opaque,
00033 Container
00034 };
00035 static const int ValidCategories = Compound + 1;
00036
00037 private:
00038 std::string m_name;
00039
00040 size_t m_size;
00041 Category m_category;
00042
00044 static bool isValidIdentifier(const std::string& identifier);
00045
00046 protected:
00047
00048
00049 Type(const std::string& name, size_t size, Category category);
00050
00051 public:
00052 virtual ~Type();
00053
00056 void setName (const std::string& name);
00061 void setSize (size_t size);
00063 std::string getName() const;
00065 std::string getBasename() const;
00067 std::string getNamespace() const;
00069 size_t getSize() const;
00071 Category getCategory() const;
00073 bool isNull() const;
00074
00080 virtual std::set<Type const*> dependsOn() const = 0;
00081
00088 virtual void modifiedDependencyAliases(Registry& registry) const;
00089
00090 bool operator == (Type const& with) const;
00091 bool operator != (Type const& with) const;
00092
00097 bool isSame(Type const& other) const;
00098
00102 bool canCastTo(Type const& to) const;
00103
00108 Type const& merge(Registry& registry) const;
00109
00111 typedef std::map<Type const*, Type const*> RecursionStack;
00112
00119 virtual Type const& merge(Registry& registry, RecursionStack& stack) const;
00120
00129 virtual bool resize(Registry& registry, std::map<std::string, std::pair<size_t, size_t> >& new_sizes);
00130
00133 virtual unsigned int getTrailingPadding() const;
00134
00135 protected:
00154 virtual bool do_compare(Type const& other, bool equality, std::map<Type const*, Type const*>& stack) const;
00155
00161 bool rec_compare(Type const& left, Type const& right, bool equality, RecursionStack& stack) const;
00162
00170 Type const* try_merge(Registry& registry, RecursionStack& stack) const;
00171
00179 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const = 0;
00180
00182 virtual bool do_resize(Registry& into, std::map<std::string, std::pair<size_t, size_t> >& new_sizes);
00183 };
00184
00185 class NullType : public Type
00186 {
00187 public:
00188 NullType(std::string const& name) : Type(name, 0, Type::NullType ) {}
00189 virtual std::set<Type const*> dependsOn() const { return std::set<Type const*>(); }
00190
00191 private:
00192 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const { return new NullType(*this); }
00193 };
00194
00199 class OpaqueType : public Type
00200 {
00201 public:
00202 OpaqueType(std::string const& name, size_t size) : Type(name, size, Type::Opaque) {}
00203 virtual std::set<Type const*> dependsOn() const { return std::set<Type const*>(); }
00204 virtual bool do_compare(Type const& other, bool equality, std::map<Type const*, Type const*>& stack) const;
00205 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const { return new OpaqueType(*this); }
00206 };
00207
00209 class Numeric : public Type
00210 {
00211 public:
00212 enum NumericCategory
00213 {
00214 SInt = Type::ValidCategories,
00215 UInt,
00216 Float
00217 };
00218 static const int ValidCategories = Float + 1;
00219
00221 NumericCategory getNumericCategory() const;
00222
00223 public:
00225 Numeric(const std::string& name, size_t size, NumericCategory category);
00226
00227 virtual std::set<Type const*> dependsOn() const { return std::set<Type const*>(); }
00228
00229 private:
00230 virtual bool do_compare(Type const& other, bool equality, RecursionStack& stack) const;
00231 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const;
00232 NumericCategory m_category;
00233 };
00234
00236 class Enum : public Type
00237 {
00238 public:
00239 typedef int integral_type;
00240 typedef std::map<std::string, int> ValueMap;
00241
00242 class AlreadyExists : public std::runtime_error
00243 {
00244 public:
00245 AlreadyExists(Type const& type, std::string const& name);
00246 };
00247 class SymbolNotFound : public std::runtime_error
00248 {
00249 public:
00250 SymbolNotFound(Type const& type, std::string const& name);
00251 };
00252 class ValueNotFound : public std::runtime_error
00253 {
00254 public:
00255 ValueNotFound(Type const& type, int value);
00256 };
00257
00258 Enum(const std::string& name, Enum::integral_type initial_value = 0);
00260 void add(std::string const& name, int value);
00263 integral_type get(std::string const& name) const;
00266 std::string get(integral_type value) const;
00267
00269 std::list<std::string> names() const;
00271 ValueMap const& values() const;
00272
00273 virtual std::set<Type const*> dependsOn() const { return std::set<Type const*>(); }
00274
00277 Enum::integral_type getNextValue() const;
00278
00279 private:
00280 virtual bool do_compare(Type const& other, bool equality, RecursionStack& stack) const;
00281 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const;
00282 integral_type m_last_value;
00283 ValueMap m_values;
00284 };
00285
00287 class Field
00288 {
00289 friend class Compound;
00290
00291 std::string m_name;
00292 const Type& m_type;
00293 size_t m_offset;
00294
00295 protected:
00296 void setOffset(size_t offset);
00297
00298 public:
00299 Field(const std::string& name, Type const& base_type);
00300
00302 std::string getName() const;
00304 const Type& getType() const;
00307 size_t getOffset() const;
00308
00309 bool operator == (Field const& field) const;
00310 };
00311
00314 class Compound : public Type
00315 {
00316 public:
00317 typedef std::list<Field> FieldList;
00318
00319 public:
00320 Compound(std::string const& name);
00321
00323 FieldList const& getFields() const;
00326 Field const* getField(const std::string& name) const;
00328 void addField(const Field& field, size_t offset);
00330 void addField(const std::string& name, const Type& type, size_t offset);
00331
00334 unsigned int getTrailingPadding() const;
00335
00336 virtual std::set<Type const*> dependsOn() const;
00337
00338 private:
00339 virtual bool do_compare(Type const& other, bool equality, RecursionStack& stack) const;
00340 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const;
00341 bool do_resize(Registry& registry, std::map<std::string, std::pair<size_t, size_t> >& new_sizes);
00342 FieldList m_fields;
00343 };
00344
00346 class Indirect : public Type
00347 {
00348 public:
00349 static const int ValidIDs = Type::Pointer | Type::Array;
00350
00351 public:
00352
00353 Indirect(std::string const& name, size_t size, Category category, Type const& on);
00354
00355 void modifiedDependencyAliases(Registry& registry) const;
00356
00357 Type const& getIndirection() const;
00358 virtual std::set<Type const*> dependsOn() const;
00359
00360 virtual Type const& merge(Registry& registry, RecursionStack& stack) const;
00361
00362 protected:
00363 virtual bool do_compare(Type const& other, bool equality, RecursionStack& stack) const;
00364 virtual bool do_resize(Registry& registry, std::map<std::string, std::pair<size_t, size_t> >& new_sizes);
00365
00372 virtual std::string getIndirectTypeName(std::string const& inside_name) const = 0;
00373
00374 private:
00375 Type const& m_indirection;
00376 };
00377
00381 class Array : public Indirect
00382 {
00383 public:
00384
00385 Array(Type const& of, size_t dimension);
00386 size_t getDimension() const;
00387 static std::string getArrayName(std::string const& base, size_t new_dim);
00388
00389 protected:
00390 virtual std::string getIndirectTypeName(std::string const& inside_name) const;
00391
00392 private:
00393 virtual bool do_compare(Type const& other, bool equality, RecursionStack& stack) const;
00394 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const;
00395 virtual bool do_resize(Registry& into, std::map<std::string, std::pair<size_t, size_t> >& new_sizes);
00396 size_t m_dimension;
00397 };
00398
00400 class Pointer : public Indirect
00401 {
00402 public:
00403 Pointer(Type const& on);
00404 static std::string getPointerName(std::string const& base);
00405
00406 protected:
00407 virtual std::string getIndirectTypeName(std::string const& inside_name) const;
00408
00409 private:
00410 virtual Type* do_merge(Registry& registry, RecursionStack& stack) const;
00411 };
00412
00413 struct UnknownContainer : public std::runtime_error
00414 {
00415 UnknownContainer(std::string const& name)
00416 : std::runtime_error("unknown container " + name) {}
00417 };
00418
00419 class ValueVisitor;
00420 class Value;
00421
00423 class Container : public Indirect
00424 {
00425 std::string m_kind;
00426
00427
00428 protected:
00429 struct DeleteIfPredicate
00430 {
00431 virtual bool should_delete(Value const& v) = 0;
00432 };
00433
00434 virtual void delete_if_impl(void* ptr, DeleteIfPredicate& pred) const = 0;
00435
00436 private:
00437 template<typename Pred>
00438 struct PredicateWrapper : public DeleteIfPredicate
00439 {
00440 Pred pred;
00441
00442 PredicateWrapper(Pred pred)
00443 : pred(pred) {}
00444
00445 virtual bool should_delete(Value const& v)
00446 {
00447 return pred(v);
00448 };
00449 };
00450
00451
00452 public:
00453 typedef std::vector<size_t> MarshalOps;
00454
00455 Container(std::string const& kind, std::string const& name, size_t size, Type const& of);
00456
00457 std::string kind() const;
00458 virtual void init(void* ptr) const = 0;
00459 virtual void destroy(void* ptr) const = 0;
00460 virtual bool visit(void* ptr, ValueVisitor& visitor) const = 0;
00461
00467 virtual bool isRandomAccess() const;
00468
00477 virtual Typelib::Value getElement(void* ptr, int idx) const;
00478
00487 virtual void setElement(void* ptr, int idx, Typelib::Value value) const;
00488
00491 virtual void clear(void* ptr) const = 0;
00492
00495 virtual void push(void* ptr, Value v) const = 0;
00496
00501 virtual bool erase(void* ptr, Value v) const = 0;
00502
00508 virtual bool compare(void* ptr, void* other) const = 0;
00509
00513 virtual void copy(void* dst, void* src) const = 0;
00514
00519 virtual long getNaturalSize() const = 0;
00520
00521 template<typename Pred>
00522 void delete_if(void* ptr, Pred pred) const
00523 {
00524 PredicateWrapper<Pred> predicate(pred);
00525 delete_if_impl(ptr, predicate);
00526 }
00527
00528 virtual size_t getElementCount(void const* ptr) const = 0;
00529
00547 virtual MarshalOps::const_iterator dump(
00548 void const* container_ptr, size_t element_count,
00549 OutputStream& stream,
00550 MarshalOps::const_iterator const begin, MarshalOps::const_iterator const end) const = 0;
00551
00568 virtual MarshalOps::const_iterator load(
00569 void* container_ptr, size_t element_count,
00570 InputStream& stream,
00571 MarshalOps::const_iterator const begin, MarshalOps::const_iterator const end) const = 0;
00572
00573 typedef Container const& (*ContainerFactory)(Registry& r, std::list<Type const*> const& base_type);
00574 typedef std::map<std::string, ContainerFactory> AvailableContainers;
00575
00576 static AvailableContainers availableContainers();
00577 static void registerContainer(std::string const& name, ContainerFactory factory);
00578 static Container const& createContainer(Registry& r, std::string const& name, Type const& on);
00579 static Container const& createContainer(Registry& r, std::string const& name, std::list<Type const*> const& on);
00580
00581 protected:
00582 virtual bool do_compare(Type const& other, bool equality, RecursionStack& stack) const;
00583 virtual ContainerFactory getFactory() const = 0;
00584 Type* do_merge(Registry& registry, RecursionStack& stack) const;
00585
00586 private:
00587 static AvailableContainers* s_available_containers;
00588 };
00589
00590 struct TypeException : public std::runtime_error
00591 {
00592 TypeException(std::string const& msg) : std::runtime_error(msg) { }
00593 };
00594
00595 struct BadCategory : public TypeException
00596 {
00597 Type::Category const found;
00598 int const expected;
00599
00600 BadCategory(Type::Category found, int expected);
00601 };
00602
00603 struct NullTypeFound : public TypeException
00604 {
00605 NullTypeFound();
00606 };
00607 };
00608
00609 #endif
00610