~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to library/grt/src/grtpp.h

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; version 2 of the
 
7
 * License.
 
8
 * 
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
12
 * GNU General Public License for more details.
 
13
 * 
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 
17
 * 02110-1301  USA
 
18
 */
 
19
 
 
20
#ifndef _GRTPP_H_
 
21
#define _GRTPP_H_
 
22
 
 
23
#ifdef __GNUC__
 
24
#include <cxxabi.h>
 
25
#endif
 
26
#include <cstring>
 
27
#include <typeinfo>
 
28
#include <list>
 
29
#include <map>
 
30
#include <deque>
 
31
#include <vector>
 
32
#include <stdexcept>
 
33
#include <boost/function.hpp>
 
34
#include <libxml/xmlmemory.h>
 
35
#include <boost/signals2.hpp>
 
36
                        
 
37
#include <glib.h>
 
38
 
 
39
#include <string>
 
40
 
 
41
#ifndef _NODLL_
 
42
# if defined(_WIN32)
 
43
# pragma warning (disable: 4275)
 
44
# pragma warning(disable:4251)
 
45
#  ifdef MYSQLGRTLIBRARY_EXPORTS
 
46
#   define MYSQLGRT_PUBLIC __declspec(dllexport)
 
47
#  else
 
48
#   define MYSQLGRT_PUBLIC __declspec(dllimport)
 
49
#  endif
 
50
 
 
51
# endif
 
52
#endif
 
53
 
 
54
#ifndef MYSQLGRT_PUBLIC
 
55
# define MYSQLGRT_PUBLIC
 
56
#endif
 
57
 
 
58
#ifdef _MSC_VER
 
59
#define THROW(...)
 
60
#else
 
61
#define THROW(...) throw (__VA_ARGS__)
 
62
#endif
 
63
 
 
64
#ifdef _WIN32
 
65
#include <hash_set>
 
66
typedef stdext::hash_set<std::string> string_hash_set;
 
67
#else
 
68
#include <ext/hash_set>
 
69
 
 
70
struct string_hash : public std::unary_function<std::string, size_t> 
 
71
{
 
72
  size_t operator() (const std::string &v) const
 
73
  {
 
74
    return __gnu_cxx::hash<const char*>()(v.c_str());
 
75
  }
 
76
};
 
77
 
 
78
typedef __gnu_cxx::hash_set<std::string, string_hash> string_hash_set;
 
79
#endif
 
80
 
 
81
 
 
82
#define GRT_VERSION "4.1.0"
 
83
 
 
84
 
 
85
 
 
86
namespace grt {
 
87
 
 
88
  class MYSQLGRT_PUBLIC os_error : public std::runtime_error
 
89
  {
 
90
  public:
 
91
    os_error(const std::string &msg) : std::runtime_error(msg) {}
 
92
    os_error(int err) : std::runtime_error(g_strerror(err)) {}
 
93
    os_error(const std::string &msg, int err) : std::runtime_error(msg+": "+g_strerror(err)) {}
 
94
  };
 
95
 
 
96
  class MYSQLGRT_PUBLIC null_value : public std::logic_error
 
97
  {
 
98
  public:
 
99
    explicit null_value(const std::string &msg) : std::logic_error(msg) {}
 
100
    explicit null_value() : std::logic_error("Attempt to operate on a NULL GRT value.") {}
 
101
  };
 
102
 
 
103
  class MYSQLGRT_PUBLIC read_only_item : public std::logic_error
 
104
  {
 
105
  public:
 
106
    explicit read_only_item(const std::string &value) : std::logic_error(value+" is read-only") {}
 
107
  };
 
108
 
 
109
  class MYSQLGRT_PUBLIC bad_item : public std::logic_error
 
110
  {
 
111
  public:
 
112
    //    virtual ~bad_item() THROW() {};
 
113
    
 
114
    bad_item(size_t index, size_t count) : std::logic_error("Index out of range.") {}
 
115
    bad_item(const std::string &name) : std::logic_error("Invalid item name '" + name + "'.") {}
 
116
  };
 
117
 
 
118
  class MYSQLGRT_PUBLIC bad_class : public std::logic_error
 
119
  {
 
120
  public:
 
121
    bad_class(const std::string &name) : std::logic_error("Invalid class "+name) {}
 
122
  };
 
123
 
 
124
  class MYSQLGRT_PUBLIC grt_runtime_error : public std::runtime_error
 
125
  {
 
126
  public:
 
127
    std::string detail;
 
128
    bool fatal;
 
129
 
 
130
    grt_runtime_error(const grt_runtime_error &other) : std::runtime_error(other), detail(other.detail), fatal(other.fatal) {}
 
131
    grt_runtime_error(const std::string &exc, const std::string &adetail, bool afatal= false) : std::runtime_error(exc), detail(adetail), fatal(afatal) {}
 
132
    
 
133
    virtual ~grt_runtime_error() THROW() {}
 
134
  };
 
135
 
 
136
  class MYSQLGRT_PUBLIC module_error : public std::runtime_error
 
137
  {
 
138
  public:
 
139
    module_error(const std::string &exc) : std::runtime_error(exc) {}
 
140
  };
 
141
 
 
142
  class MYSQLGRT_PUBLIC user_cancelled : public std::runtime_error
 
143
  {
 
144
  public:
 
145
    user_cancelled(const std::string &exc) : std::runtime_error(exc) {}
 
146
  };  
 
147
};
 
148
 
 
149
//------------------------------------------------------------------------------------------------
 
150
//------------------------------------------------------------------------------------------------
 
151
 
 
152
/** @addtogroup GRT
 
153
 * @htmlinclude GRT.html
 
154
 * 
 
155
 */
 
156
 
 
157
 
 
158
#include "grtpp_value.h"
 
159
 
 
160
 
 
161
namespace grt {
 
162
  class GRT;
 
163
  
 
164
  namespace internal
 
165
  {
 
166
    class Serializer;
 
167
    class Unserializer;
 
168
  };
 
169
 
 
170
  //------------------------------------------------------------------------------------------------
 
171
 
 
172
  /** Base GRT value reference class.
 
173
   * The Ref classes act as a smart pointer for GRT values. Because GRT
 
174
   * values are allocated on the heap and are reference counted, the Ref
 
175
   * classes will wrap around these values and perform automatic reference
 
176
   * incrementing or decrementing when statically allocated. In most cases
 
177
   * you must not directly reference or allocate a GRT value.
 
178
   * 
 
179
   * They also have methods for accessing meta-information about the value
 
180
   * like the type and implement some basic operators like assignment, ==,
 
181
   * != and <
 
182
   * 
 
183
   * The comparison operators will work on the actual GRT value wrapped,
 
184
   * even when you compare through the ValueRef type. In this case, if the
 
185
   * types of the compared values do not match they will also compare the
 
186
   * type of each value.
 
187
   *
 
188
   * @ingroup GRT
 
189
   */ 
 
190
  class MYSQLGRT_PUBLIC ValueRef
 
191
  {
 
192
  public:
 
193
    ValueRef() : _value(0) {}
 
194
 
 
195
    explicit ValueRef(internal::Value *value)
 
196
      : _value(value)
 
197
    {
 
198
      if (_value)
 
199
        _value->retain();
 
200
    }
 
201
 
 
202
    ValueRef(const ValueRef &value)
 
203
      : _value(value._value)
 
204
    {
 
205
      if (_value)
 
206
        _value->retain();
 
207
    }
 
208
 
 
209
    /*virtual*/ ~ValueRef()
 
210
    {
 
211
      if (_value)
 
212
        _value->release();
 
213
    }
 
214
 
 
215
    inline void clear() 
 
216
    { 
 
217
      if (_value) 
 
218
        _value->release(); 
 
219
      _value= 0; 
 
220
    }
 
221
 
 
222
    inline bool is_valid() const { return _value != 0; }
 
223
    inline bool is_same(const ValueRef &value) const { return valueptr() == value.valueptr(); }
 
224
 
 
225
    inline Type type() const { return _value ? _value->get_type() : UnknownType; }
 
226
    
 
227
    ValueRef &operator= (const ValueRef& other) { swap(other._value); return *this; }
 
228
    
 
229
    // for non-simple types will only check if its the same object
 
230
    inline bool operator == (const ValueRef &other) const
 
231
    {
 
232
      if (_value == other._value) return true;
 
233
      if (!_value || !other._value) return false;
 
234
      if (type() != other.type()) return false;
 
235
 
 
236
      return _value->equals(other._value);
 
237
    }
 
238
     
 
239
    inline bool operator != (const ValueRef &other) const
 
240
    {
 
241
      return !(operator ==(other));
 
242
    }
 
243
 
 
244
    // for non-simple types will check order of the pointer of the object 
 
245
    // (ie gives an arbitrary order)
 
246
    inline bool operator < (const ValueRef &other) const
 
247
    {
 
248
      if (!_value || !other._value) return _value < other._value;
 
249
      if (type() != other.type())
 
250
        return (type() < other.type());
 
251
 
 
252
      return _value->less_than(other._value);
 
253
    }
 
254
 
 
255
    std::string repr() const { return _value ? _value->repr() : "NULL"; }
 
256
 
 
257
    inline internal::Value *valueptr() const { return _value; }
 
258
 
 
259
    int refcount() const { return _value->refcount(); }
 
260
    void retain() { if (_value) _value->retain(); }
 
261
    void release() { if (_value)_value->release(); }
 
262
     
 
263
  protected:
 
264
    internal::Value *_value;
 
265
 
 
266
    void swap(internal::Value *nvalue)
 
267
    { 
 
268
      if (nvalue != _value) 
 
269
      { 
 
270
        if (_value)
 
271
          _value->release();
 
272
        _value= nvalue;
 
273
        if (_value)
 
274
          _value->retain();
 
275
      }
 
276
    }
 
277
  };
 
278
 
 
279
 
 
280
  //----------------------------------------------------------------------
 
281
  // Object Refs
 
282
  
 
283
  template<class C> class Ref;
 
284
   
 
285
  typedef Ref<internal::Object> ObjectRef;
 
286
 
 
287
    
 
288
  /** Holds a reference to a GRT object.
 
289
   * 
 
290
   * Use it as Ref<db_Table> or db_TableRef, which is an alias created along
 
291
   * auto-generated classes.
 
292
   * 
 
293
   * To allocate a new object from C++ code:
 
294
   * @code
 
295
   *   db_TableRef table(grt);
 
296
   * @endcode
 
297
   *
 
298
   * To access members and methods:
 
299
   * @code
 
300
   *   table->member();
 
301
   * @endcode
 
302
   * 
 
303
   * Reference counting is performed automatically.
 
304
   *
 
305
   * @ingroup GRT
 
306
   */ 
 
307
  template<class Class>
 
308
    class Ref : public ValueRef
 
309
  {
 
310
  public:
 
311
    typedef Class RefType;
 
312
    
 
313
    Ref()
 
314
    {
 
315
    }
 
316
 
 
317
    Ref(Class *obj)
 
318
      : ValueRef(obj)
 
319
    {
 
320
    }
 
321
 
 
322
    /** Constructor for creating and initializing a new object. 
 
323
     */
 
324
    explicit Ref(GRT *grt)
 
325
      : ValueRef(new Class(grt))
 
326
    {
 
327
      content().init();
 
328
    }
 
329
 
 
330
    Ref(const Ref<Class> &ref)
 
331
      : ValueRef(ref)
 
332
    {
 
333
#ifdef ENABLE_DEBUG
 
334
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) // this causes errors in mac, with gcc 4.2
 
335
      // just to give an error if Class is not an object
 
336
      Class::static_class_name();
 
337
#endif
 
338
#endif
 
339
    }
 
340
 
 
341
    template<class Subclass>
 
342
      Ref(const Ref<Subclass> &ref)
 
343
    {
 
344
#ifdef ENABLE_DEBUG
 
345
      // poor mans compile-time type "check". compiler will throw an error if Subclass is not derived from Class
 
346
#ifdef __GNUC__
 
347
      Class *dummy_variable_just_for_type_check __attribute__((unused))= static_cast<Subclass*>(ref.valueptr());
 
348
#else
 
349
      Class *dummy_variable_just_for_type_check= static_cast<Subclass*>(ref.valueptr());
 
350
#endif
 
351
#endif
 
352
      _value= ref.valueptr();
 
353
      retain();
 
354
    }
 
355
 
 
356
    static inline bool can_wrap(const ValueRef &value) 
 
357
    { 
 
358
      return (value.type() == ObjectType) && (!value.is_valid() || dynamic_cast<Class*>(value.valueptr()));
 
359
    }
 
360
 
 
361
    static inline Ref<Class> cast_from(const ValueRef &ov)
 
362
    {
 
363
      if (ov.is_valid())
 
364
      {
 
365
        Class *obj= dynamic_cast<Class*>(ov.valueptr());
 
366
        if (!obj)
 
367
        {
 
368
          internal::Object* object= dynamic_cast<internal::Object*>(ov.valueptr());
 
369
          if (object)
 
370
            throw grt::type_error(Class::static_class_name(), object->class_name());
 
371
          else
 
372
            throw grt::type_error(Class::static_class_name(), ov.type());
 
373
        }
 
374
        return Ref<Class>(obj);
 
375
      }
 
376
      return Ref<Class>();
 
377
    }
 
378
 
 
379
    const std::string &id() const { return content().id(); }
 
380
    const std::string &class_name() const { return content().class_name(); }
 
381
    MetaClass *get_metaclass() const { return content().get_metaclass(); }
 
382
 
 
383
    bool is_instance(MetaClass *mc) const { return content().is_instance(mc); }
 
384
    bool is_instance(const std::string &klass) const { return content().is_instance(klass); }
 
385
    template <class C>
 
386
      bool is_instance() const { return C::static_class_name().empty() ? true : content().is_instance(C::static_class_name()); }
 
387
    
 
388
    Ref<Class> &operator= (const Ref<Class>& other) { Ref<Class> tmp(other); swap(tmp._value); return *this; }
 
389
 
 
390
    bool operator == (const ValueRef& other) const { return _value == other.valueptr() || (_value && content().equals(other.valueptr())); }
 
391
    bool operator != (const ValueRef& other) const { return !(operator == (other)); }
 
392
    
 
393
    Class *operator->() const { return static_cast<Class*>(_value); }
 
394
 
 
395
    ValueRef get_member(const std::string &m) const { return content().get_member(m); }
 
396
    ValueRef get_member(const struct ClassMember *m) const;
 
397
    void set_member(const std::string &m, const ValueRef &new_value) { content().set_member(m, new_value); }
 
398
 
 
399
    std::string get_string_member(const std::string &member) const { return content().get_string_member(member); }
 
400
    internal::Double::storage_type get_double_member(const std::string &member) const { return content().get_double_member(member); }
 
401
    internal::Integer::storage_type get_integer_member(const std::string &member) const { return content().get_integer_member(member); }
 
402
    bool has_member(const std::string &member) const { return content().has_member(member); }
 
403
 
 
404
    bool has_method(const std::string &method) const { return content().has_method(method); }
 
405
//    Class *operator*() const { return static_cast<Class*>(_value); }
 
406
    
 
407
    GRT *get_grt() const { return content().get_grt(); }
 
408
    
 
409
  public:
 
410
    Class &content() const { return *static_cast<Class*>(_value); }
 
411
  };
 
412
 
 
413
  //----------------------------------------------------------------------
 
414
  // Weak Object Refs
 
415
  
 
416
  template<class C> class WeakRef;
 
417
  
 
418
  typedef WeakRef<internal::Object> WeakObjectRef;  
 
419
  
 
420
  /** Holds a weak reference to a GRT object.
 
421
   * 
 
422
   * Use it as WeakRef<db_Table>
 
423
   * 
 
424
   * Weak references will not increment the reference count of the referenced object,
 
425
   * but will be able to tell whether it has been deleted. Use it to avoid circular
 
426
   * loops and other situations where you don't want a real reference to an object.
 
427
   *
 
428
   * @ingroup GRT
 
429
   */ 
 
430
  template<class Class>
 
431
  class WeakRef
 
432
    {
 
433
    public:
 
434
      typedef Class RefType;
 
435
      
 
436
      /// unitialized weak reference is invalid
 
437
      WeakRef() : _content(0), _valid_flag(false) // unassigned means reference is undefined
 
438
      {
 
439
      }
 
440
 
 
441
      // copy constructor
 
442
      WeakRef(const WeakRef<Class> &copy)
 
443
      : _content(copy._content), _valid_flag(copy._valid_flag)
 
444
      {
 
445
      }
 
446
 
 
447
      // Create a weak-ref from a normal ref
 
448
      WeakRef(const Ref<Class> &object_ref)
 
449
      : _content(object_ref.is_valid() ? &object_ref.content() : 0), 
 
450
        _valid_flag(object_ref.is_valid() ? object_ref->weakref_valid_flag() : internal::ObjectValidFlag(false))
 
451
      {
 
452
      }
 
453
 
 
454
      // gets a real usable reference to the object
 
455
      Ref<Class> lock() const
 
456
      { 
 
457
        if (!_valid_flag.valid())
 
458
          throw std::logic_error("attempt to access invalid weak-reference");
 
459
        return Ref<Class>(_content);
 
460
      }
 
461
      
 
462
      void reset()
 
463
      {
 
464
        _content= 0; // pointer was nullified, it's a valid reference to null (ie not undefined)
 
465
        _valid_flag= internal::ObjectValidFlag(true);
 
466
      }
 
467
 
 
468
      //! Returns true if the reference is still valid, false if the referenced object is gone
 
469
      bool expired() const
 
470
      {
 
471
        return _valid_flag.valid();
 
472
      }
 
473
      
 
474
      WeakRef<Class> &operator= (const WeakRef<Class>& other) 
 
475
      { 
 
476
        WeakRef<Class> tmp(other);
 
477
        swap(tmp);
 
478
        return *this; 
 
479
      }
 
480
 
 
481
      WeakRef<Class> &operator= (const Ref<Class>& other) 
 
482
      { 
 
483
        WeakRef<Class> tmp(other);
 
484
        swap(tmp);
 
485
        return *this; 
 
486
      }
 
487
    
 
488
      void swap(Ref<Class> &other)
 
489
      {
 
490
        std::swap(_content, other._content);
 
491
        _valid_flag.swap(other._valid_flag);
 
492
      }
 
493
      
 
494
      bool operator == (const WeakRef<Class>& other) const 
 
495
      { 
 
496
        return lock() == other.lock();
 
497
      }
 
498
 
 
499
      bool operator != (const WeakRef<Class>& other) const 
 
500
      {
 
501
        return lock() != other.lock();
 
502
      }
 
503
 
 
504
    private:
 
505
      /* Create a weak reference to a raw object pointer... is not safe, so we just disallow it */
 
506
      explicit WeakRef(Class *instance) 
 
507
      : _content(instance),  // if object is null, the reference is valid, just null
 
508
      _valid_flag(instance ? instance->weakref_valid_flag() : internal::ObjectValidFlag(true))
 
509
      {
 
510
      }
 
511
      
 
512
    private:
 
513
      Class *_content;
 
514
      internal::ObjectValidFlag _valid_flag;
 
515
    };
 
516
    
 
517
  //----------------------------------------------------------------------
 
518
  // IntegerRef
 
519
 
 
520
  typedef Ref<internal::Integer> IntegerRef;
 
521
 
 
522
  /** Reference object class for integer GRT values.
 
523
   * 
 
524
   * aka IntegerRef
 
525
   * 
 
526
   * To create an integer value:
 
527
   * @code
 
528
   *   InegerRef(1234);
 
529
   * @endcode
 
530
   * 
 
531
   * An implicit constructor for long is available, so you can assign
 
532
   * to a IntegerRef as:
 
533
   * @code 
 
534
   *   IntegerRef i= 1234;
 
535
   * @endcode
 
536
   *
 
537
   * @ingroup GRT
 
538
   */ 
 
539
  template<>
 
540
  class Ref<internal::Integer> : public ValueRef
 
541
  {
 
542
  public:
 
543
    typedef internal::Integer RefType;
 
544
    typedef internal::Integer::storage_type storage_type;
 
545
 
 
546
    static inline Ref<internal::Integer> cast_from(const ValueRef &svalue)
 
547
    {
 
548
      if (svalue.is_valid() && svalue.type() != IntegerType)
 
549
        throw type_error(IntegerType, svalue.type());
 
550
      return Ref<internal::Integer>(svalue);
 
551
    }
 
552
 
 
553
    static inline storage_type extract_from(const ValueRef &svalue)
 
554
    {
 
555
      if (!svalue.is_valid() || svalue.type() != IntegerType)
 
556
        throw type_error(IntegerType, svalue.type());
 
557
      return *static_cast<internal::Integer*>(svalue.valueptr());
 
558
    }
 
559
    
 
560
    static inline bool can_wrap(const ValueRef &value) 
 
561
    { 
 
562
      return (value.type() == internal::Integer::static_type());
 
563
    }
 
564
 
 
565
    Ref() {}
 
566
 
 
567
    Ref(const Ref &value)
 
568
      : ValueRef(value)
 
569
    {}
 
570
    
 
571
    explicit Ref(internal::Integer *ptr)
 
572
      : ValueRef(ptr)
 
573
    {
 
574
    }
 
575
 
 
576
    Ref(long value)
 
577
       : ValueRef(internal::Integer::get(value))
 
578
    {
 
579
    }
 
580
 
 
581
    Ref(int value)
 
582
       : ValueRef(internal::Integer::get(value))
 
583
    {
 
584
    }
 
585
 
 
586
    inline operator storage_type () const { return *content(); }
 
587
    inline storage_type operator *() const { return *content(); }
 
588
 
 
589
    Ref<internal::Integer> &operator= (const Ref<internal::Integer>& other) { swap(other._value); return *this; }
 
590
     
 
591
    inline bool operator==(const IntegerRef &o) const
 
592
    {
 
593
      return _value == o._value || (_value && o._value && *content() == *o);
 
594
    }
 
595
     
 
596
    inline bool operator==(long v) const
 
597
    {
 
598
      return _value && (*content() == v);
 
599
    }
 
600
 
 
601
    inline bool operator==(int v) const
 
602
    {
 
603
      return _value && (*content() == v);
 
604
    }
 
605
 
 
606
    inline bool operator!=(const IntegerRef &o) const
 
607
    {
 
608
      return !(operator ==(o));
 
609
    }
 
610
 
 
611
    inline bool operator!=(long v) const
 
612
    {
 
613
      return _value && (*content() != v);
 
614
    }
 
615
 
 
616
    inline bool operator!=(int v) const
 
617
    {
 
618
      return _value && (*content() != v);
 
619
    }
 
620
 
 
621
  protected:
 
622
    explicit Ref(const ValueRef &ivalue)
 
623
    {
 
624
      if (ivalue.is_valid() && ivalue.type() != internal::Integer::static_type())
 
625
        throw type_error(internal::Integer::static_type(), ivalue.type());
 
626
      _value= ivalue.valueptr();
 
627
      if (_value)
 
628
        _value->retain();
 
629
    }
 
630
 
 
631
    internal::Integer& content() const { return *static_cast<internal::Integer*>(_value); }
 
632
  };
 
633
 
 
634
 
 
635
  //----------------------------------------------------------------------
 
636
  //DoubleRef
 
637
 
 
638
  typedef Ref<internal::Double> DoubleRef;
 
639
 
 
640
  /** Reference object class for double GRT values.
 
641
   * 
 
642
   * aka DoubleRef
 
643
   * 
 
644
   * To create a double value:
 
645
   * @code
 
646
   *   DoubleRef(12.34);
 
647
   * @endcode
 
648
   * 
 
649
   * An implicit constructor for long is available, so you can assign
 
650
   * to a DoubleRef as:
 
651
   * @code 
 
652
   *   DoubleRef i= 12.34;
 
653
   * @endcode
 
654
   *
 
655
   * @ingroup GRT
 
656
   */ 
 
657
  template<>
 
658
  class Ref<internal::Double> : public ValueRef
 
659
  {
 
660
  public:
 
661
    typedef internal::Double RefType;
 
662
    typedef internal::Double::storage_type storage_type;
 
663
 
 
664
    static inline Ref<internal::Double> cast_from(const ValueRef &svalue)
 
665
    {
 
666
      if (svalue.is_valid() && svalue.type() != DoubleType)
 
667
        throw type_error(DoubleType, svalue.type());
 
668
      return Ref<internal::Double>(svalue);
 
669
    }
 
670
 
 
671
    static inline storage_type extract_from(const ValueRef &svalue)
 
672
    {
 
673
      if (!svalue.is_valid() || svalue.type() != DoubleType)
 
674
        throw type_error(DoubleType, svalue.type());
 
675
      return *static_cast<internal::Double*>(svalue.valueptr());
 
676
    }
 
677
    
 
678
    static inline bool can_wrap(const ValueRef &value) 
 
679
    { 
 
680
      return (value.type() == internal::Double::static_type());
 
681
    }
 
682
 
 
683
    Ref() {}
 
684
 
 
685
    Ref(const Ref &value)
 
686
      : ValueRef(value)
 
687
    {}
 
688
 
 
689
    explicit Ref(internal::Double *ptr)
 
690
      : ValueRef(ptr)
 
691
    {
 
692
    }
 
693
 
 
694
    Ref(storage_type value)
 
695
       : ValueRef(internal::Double::get(value))
 
696
    {
 
697
    }
 
698
 
 
699
    inline operator storage_type () const { return *content(); }
 
700
    inline storage_type operator *() const { return *content(); }
 
701
 
 
702
    Ref<internal::Double> &operator= (const Ref<internal::Double>& other) { swap(other._value); return *this; }
 
703
 
 
704
    inline bool operator==(const DoubleRef &o) const
 
705
    {
 
706
      return _value == o._value || (_value && o._value && (*content() == *o));
 
707
    }
 
708
     
 
709
    inline bool operator==(storage_type v) const
 
710
    {
 
711
      return _value && (*content() == v);
 
712
    }
 
713
 
 
714
    inline bool operator!=(storage_type v) const
 
715
    {
 
716
      return _value && (*content() != v);
 
717
    }
 
718
 
 
719
    inline bool operator!=(const DoubleRef &o) const
 
720
    {
 
721
      return !(operator == (o));
 
722
    }
 
723
 
 
724
  protected:
 
725
 
 
726
    explicit Ref(const ValueRef &ivalue)
 
727
    {
 
728
      if (ivalue.is_valid() && ivalue.type() != internal::Double::static_type())
 
729
        throw type_error(internal::Double::static_type(), ivalue.type());
 
730
      _value= ivalue.valueptr();
 
731
      if (_value)
 
732
        _value->retain();
 
733
    }
 
734
 
 
735
    internal::Double& content() const { return *static_cast<internal::Double*>(_value); }
 
736
  };
 
737
 
 
738
 
 
739
  //----------------------------------------------------------------------
 
740
  // StringRef
 
741
 
 
742
  typedef Ref<internal::String> StringRef;
 
743
 
 
744
  /** Reference object class for string GRT values.
 
745
   * 
 
746
   * aka StringRef
 
747
   * 
 
748
   * To create a string value:
 
749
   * @code
 
750
   *   StringRef("foo");
 
751
   * @endcode
 
752
   * 
 
753
   * An implicit constructor for string is available, so you can assign
 
754
   * to a StringRef as:
 
755
   * @code 
 
756
   *   StringRef s= "foo";
 
757
   * @endcode
 
758
   *
 
759
   * @ingroup GRT
 
760
   */
 
761
  template<>
 
762
  class MYSQLGRT_PUBLIC Ref<internal::String> : public ValueRef
 
763
  {
 
764
  public:
 
765
    typedef internal::String RefType;
 
766
    typedef internal::String::storage_type storage_type;
 
767
 
 
768
    static inline Ref<internal::String> cast_from(const ValueRef &svalue)
 
769
    {
 
770
      if (svalue.is_valid() && svalue.type() != StringType)
 
771
        throw type_error(StringType, svalue.type());
 
772
      return Ref<internal::String>(svalue);
 
773
    }
 
774
    
 
775
    static inline std::string extract_from(const ValueRef &svalue)
 
776
    {
 
777
      if (!svalue.is_valid() || svalue.type() != StringType)
 
778
        throw type_error(StringType, svalue.type());
 
779
      return *static_cast<internal::String*>(svalue.valueptr());
 
780
    }
 
781
 
 
782
    static inline bool can_wrap(const ValueRef &value) 
 
783
    { 
 
784
      return (value.type() == internal::String::static_type());
 
785
    }
 
786
     
 
787
    static Ref format(const char *format, ...);
 
788
 
 
789
    Ref() {}
 
790
 
 
791
    Ref(const Ref &value)
 
792
      : ValueRef(value)
 
793
    {}
 
794
 
 
795
    explicit Ref(internal::String *ptr)
 
796
      : ValueRef(ptr)
 
797
    {
 
798
    }
 
799
 
 
800
    Ref(const std::string &value)
 
801
       : ValueRef(internal::String::get(value))
 
802
    {
 
803
    }
 
804
 
 
805
    Ref(const char *value)
 
806
       : ValueRef(internal::String::get(value))
 
807
    {
 
808
    }
 
809
 
 
810
    inline operator storage_type () const { return *content(); }
 
811
    inline storage_type operator *() const { return *content(); }
 
812
     
 
813
    const char *c_str() const { return content().c_str(); }
 
814
    bool empty() const { return content().empty(); }
 
815
 
 
816
    Ref<internal::String> &operator= (const Ref<internal::String>& other) { swap(other._value); return *this; }
 
817
 
 
818
    inline bool operator==(const StringRef &v) const
 
819
    {
 
820
      return _value == v._value || (_value && v._value && (*content() == *v));
 
821
    }
 
822
 
 
823
    inline bool operator==(const storage_type &v) const
 
824
    {
 
825
      return _value && (*content() == v);
 
826
    }
 
827
 
 
828
    inline bool operator==(const char *v) const
 
829
    {
 
830
      return _value && (strcmp(content().c_str(), v)==0);
 
831
    }
 
832
 
 
833
    inline bool operator!=(const StringRef &v) const
 
834
    {
 
835
      return !operator ==(v);
 
836
    }
 
837
 
 
838
    inline bool operator!=(const storage_type &v) const
 
839
    {
 
840
      return !operator ==(v);
 
841
    }
 
842
 
 
843
    inline bool operator!=(const char *v) const
 
844
    {
 
845
      return !operator ==(v);
 
846
    }
 
847
 
 
848
  protected:
 
849
 
 
850
    explicit Ref(const ValueRef &ivalue)
 
851
    {
 
852
      if (ivalue.is_valid() && ivalue.type() != internal::String::static_type())
 
853
        throw type_error(internal::String::static_type(), ivalue.type());
 
854
      _value= ivalue.valueptr();
 
855
      if (_value)
 
856
        _value->retain();
 
857
    }
 
858
 
 
859
    internal::String& content() const { return *static_cast<internal::String*>(_value); }
 
860
  };
 
861
 
 
862
 
 
863
  //----------------------------------------------------------------------
 
864
  // Lists
 
865
 
 
866
  template<class C>
 
867
  struct TypedListConstIterator
 
868
  {
 
869
    typedef std::random_access_iterator_tag iterator_category;
 
870
    typedef C value_type;
 
871
    typedef int difference_type;
 
872
    typedef C* pointer;
 
873
    typedef C& reference;
 
874
    typedef internal::List::raw_const_iterator IterType;
 
875
 
 
876
    IterType iter;
 
877
    
 
878
    TypedListConstIterator() : iter(0) {}
 
879
 
 
880
    TypedListConstIterator(const TypedListConstIterator &content) : iter(content.iter) {}
 
881
    
 
882
    TypedListConstIterator(const IterType &content)
 
883
      : iter(content)
 
884
    {}
 
885
 
 
886
    inline bool operator < (const TypedListConstIterator &o) const
 
887
    {
 
888
      return iter < o.iter;
 
889
    }
 
890
 
 
891
    inline Ref<C> operator *() const
 
892
    {
 
893
      return Ref<C>((C*)iter->valueptr());
 
894
    }
 
895
 
 
896
    inline bool operator == (const TypedListConstIterator &o) const
 
897
    {
 
898
      return iter == o.iter;
 
899
    }
 
900
 
 
901
    inline bool operator != (const TypedListConstIterator &o) const
 
902
    {
 
903
      return iter != o.iter;
 
904
    }
 
905
 
 
906
    inline TypedListConstIterator& operator ++()
 
907
    {
 
908
      ++iter;
 
909
      return *this;
 
910
    }
 
911
 
 
912
    inline TypedListConstIterator operator ++(int)
 
913
    {
 
914
      TypedListConstIterator temp(*this);
 
915
      ++iter;
 
916
      return temp;
 
917
    }
 
918
  };
 
919
 
 
920
  template<class C>
 
921
  struct TypedListConstReverseIterator
 
922
  {
 
923
    typedef std::random_access_iterator_tag iterator_category;
 
924
    typedef C value_type;
 
925
    typedef int difference_type;
 
926
    typedef C* pointer;
 
927
    typedef C& reference;
 
928
    typedef internal::List::raw_const_reverse_iterator IterType;
 
929
    
 
930
    IterType iter;
 
931
    
 
932
    TypedListConstReverseIterator() {}
 
933
    
 
934
    TypedListConstReverseIterator(const TypedListConstReverseIterator &content) : iter(content.iter) {}
 
935
    
 
936
    TypedListConstReverseIterator(const IterType &content)
 
937
    : iter(content)
 
938
    {}
 
939
    
 
940
    inline bool operator < (const TypedListConstReverseIterator &o) const
 
941
    {
 
942
      return iter < o.iter;
 
943
    }
 
944
    
 
945
    inline Ref<C> operator *() const
 
946
    {
 
947
      return Ref<C>((C*)iter->valueptr());
 
948
    }
 
949
    
 
950
    inline bool operator == (const TypedListConstReverseIterator &o) const
 
951
    {
 
952
      return iter == o.iter;
 
953
    }
 
954
    
 
955
    inline bool operator != (const TypedListConstReverseIterator &o) const
 
956
    {
 
957
      return iter != o.iter;
 
958
    }
 
959
    
 
960
    inline TypedListConstReverseIterator& operator ++()
 
961
    {
 
962
      ++iter;
 
963
      return *this;
 
964
    }
 
965
    
 
966
    inline TypedListConstReverseIterator operator ++(int)
 
967
    {
 
968
      TypedListConstReverseIterator temp(*this);
 
969
      ++iter;
 
970
      return temp;
 
971
    }
 
972
  };
 
973
  
 
974
  
 
975
 
 
976
  /** Base GRT list reference class.
 
977
   *
 
978
   * @ingroup GRT
 
979
   */
 
980
  class MYSQLGRT_PUBLIC BaseListRef : public ValueRef
 
981
  {
 
982
  public:
 
983
    typedef internal::List RefType;
 
984
    typedef internal::List::raw_const_iterator raw_const_iterator;
 
985
    typedef internal::List::raw_const_reverse_iterator raw_const_reverse_iterator;
 
986
    
 
987
    enum {
 
988
      npos= internal::List::npos
 
989
    };
 
990
    
 
991
    BaseListRef() {}
 
992
 
 
993
    BaseListRef(const BaseListRef &list)
 
994
      : ValueRef(list)
 
995
    {
 
996
    }
 
997
    
 
998
    BaseListRef(internal::List *list)
 
999
      : ValueRef(list)
 
1000
    {
 
1001
    }
 
1002
 
 
1003
    BaseListRef(GRT *grt, bool allow_null= true)
 
1004
      : ValueRef(new internal::List(grt, allow_null))
 
1005
    {
 
1006
    }
 
1007
 
 
1008
    BaseListRef(GRT *grt, Type type, const std::string &class_name= "", internal::Object *owner= 0, bool allow_null= true)
 
1009
       : ValueRef(owner ? new internal::OwnedList(grt, type, class_name, owner, allow_null) : new internal::List(grt, type, class_name, allow_null))
 
1010
    {
 
1011
    }
 
1012
 
 
1013
    inline Type content_type() const { return content().content_type(); };
 
1014
    inline std::string content_class_name() const { return content().content_class_name(); }
 
1015
 
 
1016
    static bool can_wrap(const ValueRef &value)
 
1017
    {
 
1018
      return value.type() == ListType;
 
1019
    }
 
1020
     
 
1021
    static BaseListRef cast_from(const ValueRef &value)
 
1022
    {
 
1023
      return BaseListRef(value);
 
1024
    }
 
1025
 
 
1026
    inline void remove(size_t index)
 
1027
    {
 
1028
      content().remove(index);
 
1029
    }
 
1030
 
 
1031
    inline void remove_all()
 
1032
    {
 
1033
      while (content().count() > 0)
 
1034
        content().remove(0);
 
1035
    }
 
1036
    
 
1037
    inline size_t count() const 
 
1038
    {
 
1039
      return is_valid() ? content().count() : 0;
 
1040
    }
 
1041
 
 
1042
    inline const ValueRef &operator[](size_t index) const
 
1043
    {
 
1044
      return content().get(index);
 
1045
    }
 
1046
 
 
1047
    inline const ValueRef &get(size_t index) const
 
1048
    {
 
1049
      return content().get(index);
 
1050
    }
 
1051
 
 
1052
    inline raw_const_iterator begin() const
 
1053
    {
 
1054
      return content().raw_begin();
 
1055
    }
 
1056
 
 
1057
    inline raw_const_iterator end() const
 
1058
    {
 
1059
      return content().raw_end();
 
1060
    }
 
1061
/*
 
1062
    inline raw_const_reverse_iterator rbegin() const
 
1063
    {
 
1064
      return content().raw_rbegin();
 
1065
    }
 
1066
    
 
1067
    inline raw_const_reverse_iterator rend() const
 
1068
    {
 
1069
      return content().raw_rend();
 
1070
    }
 
1071
  */
 
1072
    template<typename TPred>
 
1073
    bool foreach(TPred pred) const
 
1074
    {
 
1075
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
 
1076
        iter != end; ++iter)
 
1077
      {
 
1078
        if (!pred(*iter))
 
1079
          return false;
 
1080
      }
 
1081
      return true;
 
1082
    }
 
1083
 
 
1084
    inline size_t get_index(const ValueRef &value) const
 
1085
    {
 
1086
      return content().get_index(value);
 
1087
    }
 
1088
 
 
1089
    inline void reorder(size_t oindex, size_t nindex)
 
1090
    {
 
1091
      content().reorder(oindex, nindex);
 
1092
    }
 
1093
 
 
1094
    // methods beginning with g perform type checking at runtime
 
1095
    inline void gset(size_t index, const ValueRef &value)
 
1096
    {
 
1097
      content().set_checked(index, value);
 
1098
    }
 
1099
 
 
1100
    inline void ginsert(const ValueRef &value, size_t index= npos)
 
1101
    {
 
1102
      content().insert_checked(value, index);
 
1103
    }
 
1104
 
 
1105
    inline void gremove_value(const ValueRef &value)
 
1106
    {
 
1107
      content().remove(value);
 
1108
    }
 
1109
 
 
1110
    
 
1111
    inline void gset_unchecked(size_t index, const ValueRef &value)
 
1112
    {
 
1113
      content().set_unchecked(index, value);
 
1114
    }
 
1115
 
 
1116
    inline void ginsert_unchecked(const ValueRef &value, size_t index= npos)
 
1117
    {
 
1118
      content().insert_unchecked(value, index);
 
1119
    }
 
1120
 
 
1121
    GRT *get_grt() const { return content().get_grt(); }
 
1122
 
 
1123
  public:
 
1124
    inline internal::List &content() const { return *static_cast<internal::List*>(_value); }
 
1125
 
 
1126
    // For consistency with other Ref<> templates use -> operator as shortcut for content().
 
1127
    inline internal::List *operator->() const { return static_cast<internal::List*>(_value); }
 
1128
  protected:
 
1129
    explicit BaseListRef(const ValueRef &lvalue)
 
1130
    {
 
1131
      if (lvalue.is_valid() && lvalue.type() != ListType)
 
1132
        throw type_error(ListType, lvalue.type());
 
1133
      
 
1134
      _value= lvalue.valueptr();
 
1135
      if (_value)
 
1136
        _value->retain();
 
1137
    }
 
1138
  };
 
1139
 
 
1140
 
 
1141
  //----------------------------------------------------------------------
 
1142
  // ListRef<Object>
 
1143
  
 
1144
  
 
1145
  /** GRT object list reference class.
 
1146
   *
 
1147
   * @ingroup GRT
 
1148
   */
 
1149
  template<class O>
 
1150
    class ListRef : public BaseListRef
 
1151
  {
 
1152
  public:
 
1153
    typedef TypedListConstIterator<O> const_iterator;
 
1154
    typedef TypedListConstReverseIterator<O> const_reverse_iterator;
 
1155
    typedef Ref<O> value_type;
 
1156
 
 
1157
    
 
1158
    ListRef() {}
 
1159
 
 
1160
    ListRef(GRT *grt, bool allow_null= true)
 
1161
      : BaseListRef(grt, ObjectType, O::static_class_name(), 0, allow_null)
 
1162
    {
 
1163
    }
 
1164
 
 
1165
    ListRef(GRT *grt, internal::Object *owner, bool allow_null= true)
 
1166
      : BaseListRef(grt, ObjectType, O::static_class_name(), owner, allow_null)
 
1167
    {
 
1168
    }
 
1169
     
 
1170
    template<class Subclass>
 
1171
      ListRef(const ListRef<Subclass> &other)
 
1172
       : BaseListRef(other)
 
1173
    {
 
1174
       Subclass *x= 0;
 
1175
#ifdef __GNUC__
 
1176
       O *tmp __attribute__((unused))= x;// hack so that we get a compile error if Subclass is not a subclass of O
 
1177
#else
 
1178
       O *tmp= x;// hack so that we get a compile error if Subclass is not a subclass of O
 
1179
#endif
 
1180
    }
 
1181
 
 
1182
    static ListRef<O> cast_from(const ValueRef &value)
 
1183
    {
 
1184
      // check if a list
 
1185
      if (!value.is_valid() || can_wrap(value))
 
1186
        return ListRef<O>(value);
 
1187
 
 
1188
      TypeSpec expected;
 
1189
      expected.base.type= ListType;
 
1190
      expected.content.type= ObjectType;
 
1191
      expected.content.object_class= O::static_class_name();
 
1192
            
 
1193
      if (value.type() == ListType)
 
1194
      {
 
1195
        TypeSpec actual;
 
1196
        actual.base.type= ListType;
 
1197
        actual.content= BaseListRef::cast_from(value)->content_type_spec();
 
1198
        throw type_error(expected, actual); 
 
1199
      }
 
1200
      else
 
1201
        throw type_error(ListType, value.type());
 
1202
    }
 
1203
 
 
1204
    static bool can_wrap(const ValueRef &value);
 
1205
 
 
1206
    inline void insert(const Ref<O> &value, size_t index= npos)
 
1207
    {
 
1208
      content().insert_unchecked(value, index);
 
1209
    }
 
1210
 
 
1211
    inline void remove_value(const Ref<O> &value)
 
1212
    {
 
1213
      content().remove(value);
 
1214
    }
 
1215
    
 
1216
    // Return const Ref<> so that list[i]= newvalue; won't be attempted (that wouldnt work as expected)
 
1217
    inline const Ref<O> operator[](size_t index) const
 
1218
    {
 
1219
      return get(index);
 
1220
    }
 
1221
 
 
1222
    inline Ref<O> get(size_t index) const
 
1223
    {
 
1224
      return Ref<O>::cast_from(content().get(index));
 
1225
    }
 
1226
 
 
1227
    inline void set(size_t index, const Ref<O> &value)
 
1228
    {
 
1229
      content().set_unchecked(index, value);
 
1230
    }
 
1231
 
 
1232
    inline const_iterator begin() const
 
1233
    {
 
1234
      return const_iterator(content().raw_begin());
 
1235
    }
 
1236
 
 
1237
    inline const_iterator end() const
 
1238
    {
 
1239
      return const_iterator(content().raw_end());
 
1240
    }
 
1241
 
 
1242
    inline const_reverse_iterator rbegin() const
 
1243
    {
 
1244
      return const_reverse_iterator(content().raw_rbegin());
 
1245
    }
 
1246
    
 
1247
    inline const_reverse_iterator rend() const
 
1248
    {
 
1249
      return const_reverse_iterator(content().raw_rend());
 
1250
    }
 
1251
    
 
1252
    template<typename TPred>
 
1253
    bool foreach(TPred pred) const
 
1254
    {
 
1255
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
 
1256
        iter != end; ++iter)
 
1257
      {
 
1258
        Ref<O> tmp((O*)iter->valueptr());
 
1259
        if (!pred(tmp))
 
1260
          return false;
 
1261
      }
 
1262
      return true;
 
1263
    }
 
1264
 
 
1265
  protected:
 
1266
    explicit ListRef(const ValueRef &lvalue)
 
1267
      : BaseListRef(lvalue)
 
1268
    {
 
1269
      if (lvalue.is_valid() && content().content_type() != O::static_type())
 
1270
        throw type_error(O::static_type(), content().content_type(), ListType);
 
1271
    }
 
1272
  };
 
1273
 
 
1274
  typedef ListRef<internal::Object> ObjectListRef;
 
1275
 
 
1276
  //----------------------------------------------------------------------
 
1277
  // ListRef<Integer>
 
1278
 
 
1279
  typedef ListRef<internal::Integer> IntegerListRef;
 
1280
 
 
1281
  /** GRT integer list reference class.
 
1282
   *
 
1283
   * aka IntegerListRef
 
1284
   * 
 
1285
   * @ingroup GRT
 
1286
   */
 
1287
  template<>
 
1288
    class MYSQLGRT_PUBLIC ListRef<internal::Integer> : public BaseListRef
 
1289
  {
 
1290
  public:
 
1291
    ListRef()
 
1292
    {
 
1293
    }
 
1294
 
 
1295
    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
 
1296
      : BaseListRef(grt, IntegerType, "", owner, allow_null)
 
1297
    {
 
1298
    }
 
1299
 
 
1300
    static inline bool can_wrap(const ValueRef &value)
 
1301
    {
 
1302
      if (value.type() != ListType) 
 
1303
        return false; 
 
1304
      if (static_cast<internal::List*>(value.valueptr())->content_type() != IntegerType)
 
1305
        return false; 
 
1306
      return true; 
 
1307
    }
 
1308
 
 
1309
    static ListRef<internal::Integer> cast_from(const ValueRef &value)
 
1310
    {
 
1311
      return ListRef<internal::Integer>(value);
 
1312
    }
 
1313
 
 
1314
    inline void insert(const IntegerRef &value, size_t index= npos)
 
1315
    {
 
1316
      content().insert_unchecked(value, index);
 
1317
    }
 
1318
 
 
1319
    inline IntegerRef operator[](size_t index) const
 
1320
    {
 
1321
      return get(index);
 
1322
    }
 
1323
 
 
1324
    inline IntegerRef get(size_t index) const
 
1325
    {
 
1326
      return IntegerRef::cast_from(content().get(index));
 
1327
    }
 
1328
 
 
1329
    inline void set(size_t index, const IntegerRef &value)
 
1330
    {
 
1331
      content().set_unchecked(index, value);
 
1332
    }
 
1333
 
 
1334
    template<typename TPred>
 
1335
    bool foreach(TPred pred) const
 
1336
    {
 
1337
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
 
1338
        iter != end; ++iter)
 
1339
      {
 
1340
        if (!pred(*(internal::Integer*)iter->valueptr()))
 
1341
          return false;
 
1342
      }
 
1343
      return true;
 
1344
    }
 
1345
 
 
1346
    inline void remove_value(const IntegerRef &value)
 
1347
    {
 
1348
      content().remove(value);
 
1349
    }
 
1350
 
 
1351
  protected:
 
1352
    explicit ListRef<internal::Integer>(const ValueRef &lvalue)
 
1353
      : BaseListRef(lvalue)
 
1354
    {
 
1355
      if (lvalue.is_valid() && content().content_type() != IntegerType)
 
1356
        throw type_error(IntegerType, content().content_type(), ListType);
 
1357
    }
 
1358
  };
 
1359
 
 
1360
 
 
1361
  //----------------------------------------------------------------------
 
1362
  // ListRef<Double>
 
1363
 
 
1364
  typedef ListRef<internal::Double> DoubleListRef;
 
1365
 
 
1366
  /** GRT double number list reference class.
 
1367
   *
 
1368
   * aka DoubleListRef
 
1369
   * 
 
1370
   * @ingroup GRT
 
1371
   */
 
1372
  template<> 
 
1373
  class MYSQLGRT_PUBLIC ListRef<internal::Double> : public BaseListRef
 
1374
  {
 
1375
  public:
 
1376
    ListRef()
 
1377
    {
 
1378
    }
 
1379
 
 
1380
    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
 
1381
      : BaseListRef(grt, DoubleType, "", owner, allow_null)
 
1382
    {
 
1383
    }
 
1384
    
 
1385
    static inline bool can_wrap(const ValueRef &value) 
 
1386
    { 
 
1387
      if (value.type() != ListType) 
 
1388
        return false;
 
1389
      if (static_cast<internal::List*>(value.valueptr())->content_type() != DoubleType)
 
1390
        return false; 
 
1391
      return true; 
 
1392
    }
 
1393
 
 
1394
    static ListRef<internal::Double> cast_from(const ValueRef &value)
 
1395
    {
 
1396
      return ListRef<internal::Double>(value);
 
1397
    }
 
1398
 
 
1399
    inline void insert(const DoubleRef &value, size_t index= npos)
 
1400
    { 
 
1401
      content().insert_unchecked(value, index);
 
1402
    }
 
1403
 
 
1404
    inline DoubleRef operator[](size_t index) const
 
1405
    {
 
1406
      return get(index);
 
1407
    }
 
1408
 
 
1409
    inline DoubleRef get(size_t index) const
 
1410
    {
 
1411
      return DoubleRef::cast_from(content().get(index));
 
1412
    }
 
1413
 
 
1414
    inline void set(size_t index, const DoubleRef &value)
 
1415
    {
 
1416
      content().set_unchecked(index, value);
 
1417
    }
 
1418
 
 
1419
    template<typename TPred>
 
1420
    bool foreach(TPred pred) const
 
1421
    {
 
1422
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
 
1423
        iter != end; ++iter)
 
1424
      {
 
1425
        if (!pred(*(internal::Double*)iter->valueptr()))
 
1426
          return false;
 
1427
      }
 
1428
      return true;
 
1429
    }
 
1430
 
 
1431
    inline void remove_value(const DoubleRef &value)
 
1432
    {
 
1433
      content().remove(value);
 
1434
    }
 
1435
 
 
1436
  protected:
 
1437
    explicit ListRef(const ValueRef &lvalue)
 
1438
      : BaseListRef(lvalue)
 
1439
    {
 
1440
      if (lvalue.is_valid() && content().content_type() != DoubleType)
 
1441
        throw type_error(DoubleType, content().content_type(), ListType);
 
1442
    }
 
1443
  };
 
1444
 
 
1445
 
 
1446
  //----------------------------------------------------------------------
 
1447
  // ListRef<internal::String>
 
1448
 
 
1449
  typedef ListRef<internal::String> StringListRef;
 
1450
 
 
1451
  /** GRT string list reference class.
 
1452
   *
 
1453
   * aka StringListRef
 
1454
   * 
 
1455
   * @ingroup GRT
 
1456
   */
 
1457
  template<> 
 
1458
    class MYSQLGRT_PUBLIC ListRef<internal::String> : public BaseListRef
 
1459
  {
 
1460
  public:
 
1461
    typedef TypedListConstIterator<internal::String> const_iterator;
 
1462
    typedef TypedListConstReverseIterator<internal::String> const_reverse_iterator;
 
1463
    
 
1464
    ListRef()
 
1465
    {
 
1466
    }
 
1467
 
 
1468
    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
 
1469
      : BaseListRef(grt, StringType, "", owner, allow_null)
 
1470
    {
 
1471
    }
 
1472
 
 
1473
    static inline bool can_wrap(const ValueRef &value) 
 
1474
    { 
 
1475
      if (value.type() != ListType) 
 
1476
        return false; 
 
1477
      if (static_cast<internal::List*>(value.valueptr())->content_type() != StringType)
 
1478
        return false; 
 
1479
      return true;
 
1480
    }
 
1481
 
 
1482
    static ListRef<internal::String> cast_from(const ValueRef &value) THROW(type_error)
 
1483
    {
 
1484
      return ListRef<internal::String>(value);
 
1485
    }
 
1486
 
 
1487
    inline void insert(const StringRef &value, size_t index= npos)
 
1488
    { 
 
1489
      content().insert_unchecked(value, index);
 
1490
    }
 
1491
 
 
1492
    /*
 
1493
    inline Reference operator[](size_t index) THROW (bad_item)
 
1494
    {
 
1495
//      return 
 
1496
    }*/
 
1497
 
 
1498
    inline StringRef operator[](size_t index) const
 
1499
    {
 
1500
      return get(index);
 
1501
    }
 
1502
 
 
1503
    inline StringRef get(size_t index) const THROW (bad_item)
 
1504
    {
 
1505
      return StringRef::cast_from(content().get(index));
 
1506
    }
 
1507
 
 
1508
    inline void set(size_t index, const StringRef &value) THROW (bad_item, std::invalid_argument)
 
1509
    {
 
1510
      content().set_unchecked(index, value);
 
1511
    }
 
1512
 
 
1513
    inline const_iterator begin() const
 
1514
    {
 
1515
      return const_iterator(content().raw_begin());
 
1516
    }
 
1517
 
 
1518
    inline const_iterator end() const
 
1519
    {
 
1520
      return const_iterator(content().raw_end());
 
1521
    }
 
1522
 
 
1523
    inline const_reverse_iterator rbegin() const
 
1524
    {
 
1525
      return const_reverse_iterator(content().raw_rbegin());
 
1526
    }
 
1527
    
 
1528
    inline const_reverse_iterator rend() const
 
1529
    {
 
1530
      return const_reverse_iterator(content().raw_rend());
 
1531
    }
 
1532
    
 
1533
    template<typename TPred>
 
1534
    bool foreach(TPred pred) const
 
1535
    {
 
1536
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
 
1537
        iter != end; ++iter)
 
1538
      {
 
1539
        if (!pred(*(internal::String*)iter->valueptr()))
 
1540
          return false;
 
1541
      }
 
1542
      return true;
 
1543
    }
 
1544
 
 
1545
    inline void remove_value(const StringRef &value)
 
1546
    {
 
1547
      content().remove(value);
 
1548
    }
 
1549
 
 
1550
    inline size_t get_index(const std::string &str)
 
1551
    {
 
1552
      return BaseListRef::get_index(StringRef(str));
 
1553
    }
 
1554
 
 
1555
  protected:
 
1556
    explicit ListRef(const ValueRef &lvalue)
 
1557
      : BaseListRef(lvalue)
 
1558
    {
 
1559
      if (lvalue.is_valid() && content().content_type() != StringType)
 
1560
        throw type_error(StringType, content().content_type(), ListType);
 
1561
    }
 
1562
  };
 
1563
 
 
1564
 
 
1565
  //----------------------------------------------------------------------
 
1566
  // DictRef.
 
1567
 
 
1568
  /** GRT dictionary reference class.
 
1569
   * 
 
1570
   * @ingroup GRT
 
1571
   */
 
1572
  class MYSQLGRT_PUBLIC DictRef : public ValueRef
 
1573
  {
 
1574
  public:
 
1575
    typedef internal::Dict RefType;
 
1576
 
 
1577
    typedef internal::Dict::const_iterator const_iterator;
 
1578
 
 
1579
  public:
 
1580
    DictRef() {}
 
1581
 
 
1582
    DictRef(GRT *grt, bool allow_null= true)
 
1583
      : ValueRef(new internal::Dict(grt, allow_null))
 
1584
    {
 
1585
    }
 
1586
 
 
1587
    DictRef(GRT *grt, Type type, const std::string &cclass="", bool allow_null= true)
 
1588
      : ValueRef(new internal::Dict(grt, type, cclass, allow_null))
 
1589
    {
 
1590
    }
 
1591
 
 
1592
    DictRef(internal::Dict *dict)
 
1593
      : ValueRef(dict)
 
1594
    {
 
1595
    }
 
1596
 
 
1597
    DictRef(GRT *grt, internal::Object *owner, bool allow_null= true)
 
1598
      : ValueRef(new internal::OwnedDict(grt, AnyType, "", owner, allow_null))
 
1599
    {
 
1600
    }
 
1601
 
 
1602
    DictRef(GRT *grt, Type type, const std::string &cclass, internal::Object *owner, bool allow_null= true)
 
1603
      : ValueRef(new internal::OwnedDict(grt, type, cclass, owner, allow_null))
 
1604
    {
 
1605
    }
 
1606
 
 
1607
    static DictRef cast_from(const ValueRef& ivalue)
 
1608
    {
 
1609
      if (ivalue.is_valid() && ivalue.type() != DictType)
 
1610
        throw type_error(DictType, ivalue.type());
 
1611
      return DictRef(ivalue);
 
1612
    }
 
1613
 
 
1614
    inline Type content_type() const { return content().content_type(); };
 
1615
    inline std::string content_class_name() const { return content().content_class_name(); }
 
1616
 
 
1617
    const_iterator begin() const { return content().begin(); }
 
1618
    const_iterator end() const { return content().end(); }
 
1619
    
 
1620
    template<typename TPred>
 
1621
    bool foreach(TPred pred) const
 
1622
    {
 
1623
      for (const_iterator end= content().end(), iter= content().begin();
 
1624
        iter != end; ++iter)
 
1625
      {
 
1626
        if (!pred(iter->first, iter->second))
 
1627
          return false;
 
1628
      }
 
1629
      return true;
 
1630
    }
 
1631
 
 
1632
    inline bool has_key(const std::string &k) const
 
1633
    {
 
1634
      return content().has_key(k);
 
1635
    }
 
1636
 
 
1637
    inline ValueRef operator[](const std::string &k) const
 
1638
    {
 
1639
      return get(k);
 
1640
    }
 
1641
 
 
1642
    inline DictRef& operator = (const DictRef &o) { DictRef tmp(o); swap(o.valueptr()); return *this; }
 
1643
 
 
1644
/*
 
1645
    inline Reference operator[](const std::string &k)
 
1646
    {
 
1647
      if (!has_key(k))
 
1648
        throw bad_item(k);
 
1649
      return Reference(this, k);
 
1650
    }
 
1651
  */ 
 
1652
    inline size_t count() const { return content().count(); }
 
1653
    
 
1654
    inline void remove(const std::string &k)
 
1655
    {
 
1656
      content().remove(k);
 
1657
    }
 
1658
 
 
1659
    void reset_entries()
 
1660
    {
 
1661
      content().reset_entries();
 
1662
    }
 
1663
 
 
1664
    inline ValueRef get(const std::string &k) const
 
1665
    {
 
1666
      return ValueRef(content().get(k));
 
1667
    }
 
1668
 
 
1669
    inline ValueRef get(const std::string &k, const ValueRef &defvalue) const
 
1670
    {
 
1671
      // No need to check here if the key exists.
 
1672
      // If it does not then an invalid ValueRef will be returned.
 
1673
      ValueRef tmp= content().get(k);
 
1674
      if (!tmp.is_valid())
 
1675
        return defvalue;
 
1676
      return tmp;
 
1677
    }
 
1678
 
 
1679
    std::string get_string(const std::string &k, const std::string &defvalue="") const
 
1680
    {
 
1681
      ValueRef value= get(k);
 
1682
      if (value.is_valid())
 
1683
        return StringRef::extract_from(value);
 
1684
      return defvalue;
 
1685
    }
 
1686
 
 
1687
    internal::Integer::storage_type get_int(const std::string &k, internal::Integer::storage_type defvalue=0) const
 
1688
    {
 
1689
      ValueRef value= get(k);
 
1690
      if (value.is_valid())
 
1691
        return IntegerRef::extract_from(value);
 
1692
      return defvalue;
 
1693
    }
 
1694
 
 
1695
    internal::Double::storage_type get_double(const std::string &k, internal::Double::storage_type defvalue=0.0) const
 
1696
    {
 
1697
      ValueRef value= get(k);
 
1698
      if (value.is_valid())
 
1699
        return DoubleRef::extract_from(value);
 
1700
      return defvalue;
 
1701
    }
 
1702
 
 
1703
    inline void set(const std::string &k, const ValueRef &value)
 
1704
    {
 
1705
      content().set(k, value);
 
1706
    }
 
1707
 
 
1708
    inline void gset(const std::string &k, const std::string &value)
 
1709
    {
 
1710
      content().set(k, StringRef(value));
 
1711
    }
 
1712
 
 
1713
    inline void gset(const std::string &k, long value)
 
1714
    {
 
1715
      content().set(k, IntegerRef(value));
 
1716
    }
 
1717
    
 
1718
    inline void gset(const std::string &k, int value)
 
1719
    {
 
1720
      content().set(k, IntegerRef(value));
 
1721
    }
 
1722
 
 
1723
    inline void gset(const std::string &k, internal::Double::storage_type value)
 
1724
    {
 
1725
      content().set(k, DoubleRef(value));
 
1726
    }
 
1727
 
 
1728
    inline GRT *get_grt() const
 
1729
    {
 
1730
      return content().get_grt();
 
1731
    }
 
1732
    
 
1733
    inline internal::Dict &content() const { return *static_cast<internal::Dict*>(_value); }
 
1734
 
 
1735
  protected:
 
1736
    explicit DictRef(const ValueRef &dvalue)
 
1737
      : ValueRef(dvalue)
 
1738
    {
 
1739
      if (dvalue.is_valid() && dvalue.type() != DictType)
 
1740
        throw type_error(DictType, dvalue.type());
 
1741
    }
 
1742
  };
 
1743
 
 
1744
  //--------------------------------------------------------------------------------------------------
 
1745
 
 
1746
  typedef ListRef<internal::Dict> DictListRef;
 
1747
 
 
1748
  /** GRT Dict list reference class.
 
1749
   *
 
1750
   * aka DictListRef
 
1751
   * 
 
1752
   * @ingroup GRT
 
1753
   */
 
1754
  template<>
 
1755
    class MYSQLGRT_PUBLIC ListRef<internal::Dict> : public BaseListRef
 
1756
  {
 
1757
  public:
 
1758
    ListRef()
 
1759
    {
 
1760
    }
 
1761
 
 
1762
    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
 
1763
      : BaseListRef(grt, DictType, "", owner, allow_null)
 
1764
    {
 
1765
    }
 
1766
 
 
1767
    static inline bool can_wrap(const ValueRef &value)
 
1768
    {
 
1769
      if (value.type() != ListType) 
 
1770
        return false; 
 
1771
      if (static_cast<internal::List*>(value.valueptr())->content_type() != DictType)
 
1772
        return false; 
 
1773
      return true; 
 
1774
    }
 
1775
 
 
1776
    static ListRef<internal::Dict> cast_from(const ValueRef &value)
 
1777
    {
 
1778
      return ListRef<internal::Dict>(value);
 
1779
    }
 
1780
 
 
1781
    inline void insert(const DictRef &value, size_t index= npos)
 
1782
    {
 
1783
      content().insert_unchecked(value, index);
 
1784
    }
 
1785
 
 
1786
    inline DictRef operator[](size_t index) const
 
1787
    {
 
1788
      return get(index);
 
1789
    }
 
1790
 
 
1791
    inline DictRef get(size_t index) const
 
1792
    {
 
1793
      return DictRef::cast_from(content().get(index));
 
1794
    }
 
1795
 
 
1796
    inline void set(size_t index, const DictRef &value)
 
1797
    {
 
1798
      content().set_unchecked(index, value);
 
1799
    }
 
1800
 
 
1801
    template<typename TPred>
 
1802
    bool foreach(TPred pred) const
 
1803
    {
 
1804
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
 
1805
        iter != end; ++iter)
 
1806
      {
 
1807
        if (!pred(*(internal::Dict*)iter->valueptr()))
 
1808
          return false;
 
1809
      }
 
1810
      return true;
 
1811
    }
 
1812
 
 
1813
    inline void remove_value(const DictRef &value)
 
1814
    {
 
1815
      content().remove(value);
 
1816
    }
 
1817
 
 
1818
  protected:
 
1819
    explicit ListRef<internal::Dict>(const ValueRef &lvalue)
 
1820
      : BaseListRef(lvalue)
 
1821
    {
 
1822
      if (lvalue.is_valid() && content().content_type() != DictType)
 
1823
        throw type_error(DictType, content().content_type(), ListType);
 
1824
    }
 
1825
  };
 
1826
 
 
1827
 
 
1828
//--------------------------------------------------------------------------------------------------
 
1829
 
 
1830
  struct MYSQLGRT_PUBLIC ArgSpec
 
1831
  {
 
1832
    std::string name;
 
1833
    std::string doc;
 
1834
    TypeSpec type;
 
1835
  };    
 
1836
  typedef std::vector<ArgSpec> ArgSpecList;
 
1837
 
 
1838
 
 
1839
  class PropertyBase
 
1840
  {
 
1841
  public:
 
1842
    virtual bool has_setter() const= 0;
 
1843
       
 
1844
    virtual void set(internal::Object *obj, const grt::ValueRef &value)= 0;
 
1845
    virtual grt::ValueRef get(const internal::Object *obj) const= 0;
 
1846
  };
 
1847
 
 
1848
 
 
1849
  /** Describes a GRT object member variable.
 
1850
   * Contains information about a member variable for a GRT metaclass.
 
1851
   * The meta-information in this is read from the struct*.xml files but
 
1852
   * the property pointer is set at runtime when each class registers itself
 
1853
   * with the GRT.
 
1854
   */
 
1855
  struct MYSQLGRT_PUBLIC ClassMember
 
1856
  {
 
1857
    std::string name;
 
1858
    TypeSpec type;
 
1859
    std::string default_value;
 
1860
    bool read_only; //!< member not directly settable (setter still needed for unserializing)
 
1861
    bool delegate_get; //!< getter is user implemented
 
1862
    bool delegate_set; //!< setter is user implemented
 
1863
    bool private_; //!< member has no getter/setter and is not stored
 
1864
    bool calculated; //!< whether a instance var should be created for this value
 
1865
    bool owned_object; //!< ref object is owned by this one (owned)
 
1866
    bool overrides; //!< member overrides another one
 
1867
    bool null_content_allowed; //!< whether inserting NULL values to a list or dict is allowed (allow-null)
 
1868
    
 
1869
    //! set by class when registering
 
1870
    PropertyBase *property;
 
1871
  };
 
1872
 
 
1873
 
 
1874
  /** Describes a GRT object method.
 
1875
   * Contains information about a method for a GRT metaclass.
 
1876
   * The meta-information in this is read from the struct*.xml files but
 
1877
   * the method pointer is set at runtime when each class registers itself
 
1878
   * with the GRT. 
 
1879
   */
 
1880
  struct MYSQLGRT_PUBLIC ClassMethod
 
1881
  {
 
1882
    typedef ValueRef (*Function)(internal::Object *self, const BaseListRef &args);
 
1883
 
 
1884
    std::string name;
 
1885
    // for stuff to be re-routed to methods
 
1886
    std::string module_name;
 
1887
    std::string module_function;
 
1888
    
 
1889
    TypeSpec ret_type;
 
1890
    ArgSpecList arg_types;
 
1891
    
 
1892
    bool constructor;
 
1893
    bool abstract;
 
1894
 
 
1895
    Function function;
 
1896
  };
 
1897
 
 
1898
  class Validator
 
1899
  {
 
1900
  public:
 
1901
    typedef boost::function<void (const ObjectRef&, const std::string&, const int)> MessageSlot;
 
1902
 
 
1903
    typedef std::string Tag;
 
1904
    
 
1905
    virtual ~Validator() {};
 
1906
    virtual int validate(const Tag& what, const ObjectRef& obj) = 0;
 
1907
  };
 
1908
  
 
1909
  /** GRT Class descriptor, formerly known as "struct".
 
1910
   * Contains information about member variables and methods of a GRT class/object.
 
1911
   * The class descriptions are loaded from XML files, which contain
 
1912
   * the list of members and methods with information about types and
 
1913
   * other metadata. This information is used for generating C++ classes
 
1914
   * that actually implement these classes and also for exposing the
 
1915
   * interface to these classes to the scripting interface (such as Lua).
 
1916
   * 
 
1917
   * @ingroup GRT
 
1918
   */
 
1919
  class MYSQLGRT_PUBLIC MetaClass//
 
1920
  {
 
1921
  public:
 
1922
    template<class C,class T>
 
1923
      class Property : public PropertyBase
 
1924
    {
 
1925
    protected:
 
1926
      void (C::*setter)(const T &value);
 
1927
      T (C::*getter)() const;
 
1928
 
 
1929
    public:
 
1930
      Property(T (C::*agetter)() const, void (C::*asetter)(const T &value)= 0)
 
1931
        : setter(asetter), getter(agetter) {}
 
1932
      
 
1933
      virtual ~Property() {}
 
1934
 
 
1935
      virtual bool has_setter() const
 
1936
      {
 
1937
        return setter!=0;
 
1938
      }
 
1939
       
 
1940
      virtual void set(internal::Object *obj, const grt::ValueRef &value)
 
1941
      {
 
1942
        (((C*)obj)->*setter)(T::cast_from(value));
 
1943
      }
 
1944
 
 
1945
      virtual grt::ValueRef get(const internal::Object *obj) const
 
1946
      {
 
1947
        return (((C*)obj)->*getter)();
 
1948
      }
 
1949
    };
 
1950
 
 
1951
    typedef ObjectRef (*Allocator)(GRT *grt);
 
1952
 
 
1953
    typedef ClassMember Member;
 
1954
    typedef ClassMethod Method;
 
1955
    
 
1956
    enum SignalArgType
 
1957
    {
 
1958
      BoolSArg,
 
1959
      IntSArg,
 
1960
      DoubleSArg,
 
1961
      StringSArg,
 
1962
      ObjectSArg
 
1963
    };
 
1964
 
 
1965
    struct SignalArg
 
1966
    {
 
1967
      std::string name;
 
1968
      SignalArgType type;
 
1969
      std::string object_class;
 
1970
    };
 
1971
 
 
1972
    /** Describes a signal from a GRT object. 
 
1973
     * 
 
1974
     */ 
 
1975
    struct MYSQLGRT_PUBLIC Signal
 
1976
    {
 
1977
      std::string name;
 
1978
 
 
1979
      std::vector<SignalArg> arg_types;
 
1980
    };
 
1981
 
 
1982
 
 
1983
    typedef std::map<std::string,Member> MemberList;
 
1984
    typedef std::map<std::string,Method> MethodList;
 
1985
    typedef std::list<Signal> SignalList;
 
1986
    typedef std::vector<Validator*> ValidatorList;
 
1987
 
 
1988
  public:
 
1989
    const std::string &name() const { return _name; }
 
1990
    GRT *get_grt() const { return _grt; }
 
1991
    MetaClass *parent() const { return _parent; }
 
1992
    
 
1993
    unsigned int crc32() const { return _crc32; }
 
1994
 
 
1995
    /** Calls slot iterating through all members of the metaclass.
 
1996
    * 
 
1997
    * The slot will be called for each member of the metaclass,
 
1998
    * including inherited ones. If a member is overriden,
 
1999
    * it will be called only once, for the "topmost" one.
 
2000
    * The slot must return true as long as the iteration is
 
2001
    * to be continued. Returning false will stop it.
 
2002
    * 
 
2003
    * @return true if iteration was completed and false if it
 
2004
    * was cancelled by the slot before completion.
 
2005
    */
 
2006
    template<typename TPred>
 
2007
    bool foreach_member(TPred pred)
 
2008
    {
 
2009
      // set of already seen members (only overriden ones)
 
2010
      string_hash_set seen;
 
2011
      MetaClass *mc= this;
 
2012
 
 
2013
      do
 
2014
      {
 
2015
        for (MemberList::const_iterator mem= mc->_members.begin(); mem != mc->_members.end(); ++mem)
 
2016
        {
 
2017
          if (seen.find(mem->first) != seen.end())
 
2018
            continue;
 
2019
          seen.insert(mem->first);
 
2020
 
 
2021
          if (!pred(&mem->second))
 
2022
            return false;
 
2023
        }
 
2024
        mc= mc->_parent;
 
2025
      }
 
2026
      while (mc != 0);
 
2027
 
 
2028
      return true;
 
2029
    }
 
2030
 
 
2031
    /** Calls slot iterating through all methods of the metaclass.
 
2032
    * 
 
2033
    * The slot will be called for each method of the metaclass,
 
2034
    * including inherited ones. If a method is overriden,
 
2035
    * it will be called only once, for the "topmost" one.
 
2036
    * The slot must return true as long as the iteration is
 
2037
    * to be continued. Returning false will stop it.
 
2038
    * 
 
2039
    * @return true if iteration was completed and false if it
 
2040
    * was cancelled by the slot before completion.
 
2041
    */
 
2042
 
 
2043
    template<typename TPred>
 
2044
    bool foreach_method(TPred pred)
 
2045
    {
 
2046
      // set of already seen methods (only overriden ones)
 
2047
      string_hash_set seen;
 
2048
      MetaClass *mc= this;
 
2049
 
 
2050
      do
 
2051
      {
 
2052
        for (MethodList::const_iterator mem= mc->_methods.begin(); mem != mc->_methods.end(); ++mem)
 
2053
        {
 
2054
          if (seen.find(mem->first) != seen.end())
 
2055
            continue;
 
2056
          seen.insert(mem->first);
 
2057
 
 
2058
          if (!pred(&mem->second))
 
2059
            return false;
 
2060
        }
 
2061
        mc= mc->_parent;
 
2062
      }
 
2063
      while (mc != 0);
 
2064
 
 
2065
      return true;
 
2066
    }
 
2067
 
 
2068
    /** Calls slot iterating through all signals of the metaclass.
 
2069
    * 
 
2070
    * The slot will be called for each signal of the metaclass,
 
2071
    * including inherited ones.
 
2072
    * The slot must return true as long as the iteration is
 
2073
    * to be continued. Returning false will stop it.
 
2074
    * 
 
2075
    * @return true if iteration was completed and false if it
 
2076
    * was cancelled by the slot before completion.
 
2077
    */
 
2078
    template<typename TPred>
 
2079
    bool foreach_signal(TPred pred)
 
2080
    {
 
2081
      // set of already seen methods (only overriden ones)
 
2082
      string_hash_set seen;
 
2083
      MetaClass *mc= this;
 
2084
 
 
2085
      do
 
2086
      {
 
2087
        for (SignalList::const_iterator mem= mc->_signals.begin(); mem != mc->_signals.end(); ++mem)
 
2088
        {
 
2089
          if (seen.find(mem->name) != seen.end())
 
2090
            continue;
 
2091
          seen.insert(mem->name);
 
2092
 
 
2093
          if (!pred(&*mem))
 
2094
            return false;
 
2095
        }
 
2096
        mc= mc->_parent;
 
2097
      }
 
2098
      while (mc != 0);
 
2099
 
 
2100
      return true;
 
2101
    }
 
2102
 
 
2103
 
 
2104
 
 
2105
    /** Applies all validators to obj and tag
 
2106
     *  
 
2107
     * @return true upon success and false if any validator has failed
 
2108
     */
 
2109
    bool foreach_validator(const ObjectRef& obj, const Validator::Tag& tag);
 
2110
 
 
2111
    inline const MemberList &get_members_partial() { return _members; }
 
2112
    inline const MethodList &get_methods_partial() { return _methods; }
 
2113
    inline const SignalList &get_signals_partial() { return _signals; }
 
2114
 
 
2115
    bool is_a(const std::string &name) const;
 
2116
    bool is_a(MetaClass *struc) const;
 
2117
 
 
2118
    bool has_member(const std::string &member) const;
 
2119
    bool has_method(const std::string &method) const;
 
2120
 
 
2121
    const Member *get_member_info(const std::string &member) const;
 
2122
    const Method *get_method_info(const std::string &method) const;
 
2123
    
 
2124
    TypeSpec get_member_type(const std::string &member) const;
 
2125
 
 
2126
    std::string get_attribute(const std::string &attr, bool search_parents=true);
 
2127
    std::string get_member_attribute(const std::string &member, const std::string &attr, bool search_parents=true);
 
2128
 
 
2129
    bool is_abstract() const;
 
2130
    
 
2131
    void set_member_value(internal::Object* object, const std::string &name, const ValueRef &value);
 
2132
    ValueRef get_member_value(const internal::Object *object, const std::string &name);
 
2133
    ValueRef get_member_value(const internal::Object *object, const Member *member);
 
2134
 
 
2135
    ValueRef call_method(internal::Object *object, const std::string &name, const BaseListRef &args);
 
2136
    ValueRef call_method(internal::Object *object, const Method *method, const BaseListRef &args);
 
2137
 
 
2138
    ObjectRef allocate();
 
2139
 
 
2140
  public:
 
2141
    // for use by GRT only
 
2142
    ~MetaClass();
 
2143
 
 
2144
    static MetaClass* create_base_class(GRT *grt);
 
2145
    static MetaClass* from_xml(GRT *grt, const std::string &source, xmlNodePtr node);
 
2146
    bool placeholder() const { return _placeholder; }
 
2147
    bool validate();
 
2148
    bool is_bound() const;
 
2149
    std::string source() { return _source; }
 
2150
    
 
2151
    bool force_impl() const { return _force_impl; }
 
2152
    bool watch_lists() const { return _watch_lists; }
 
2153
    bool watch_dicts() const { return _watch_dicts; }
 
2154
    bool impl_data() const { return _impl_data; }
 
2155
    
 
2156
    void set_member_internal(internal::Object* object, const std::string &name, const ValueRef &value, bool force);
 
2157
     
 
2158
  public: // for use by Objects during registration
 
2159
    void bind_allocator(Allocator alloc);
 
2160
    void bind_member(const std::string &name, PropertyBase *prop);
 
2161
    
 
2162
    void bind_method(const std::string &name, Method::Function method);
 
2163
    void add_validator(Validator* v);
 
2164
    void remove_validator(Validator* v);
 
2165
 
 
2166
  protected:
 
2167
    friend class Serializer;
 
2168
    friend class Unserializer;
 
2169
 
 
2170
    MetaClass(GRT *grt);
 
2171
    void load_xml(xmlNodePtr node);
 
2172
    void load_attribute_list(xmlNodePtr node, const std::string &member= "");
 
2173
    
 
2174
    GRT *_grt;
 
2175
    
 
2176
    std::string _name;
 
2177
    MetaClass* _parent;
 
2178
    
 
2179
    std::string _source;
 
2180
    
 
2181
    Allocator _alloc;
 
2182
    
 
2183
    std::map<std::string,std::string> _attributes;
 
2184
    MemberList _members;
 
2185
    MethodList _methods;
 
2186
    SignalList _signals;
 
2187
    ValidatorList _validators;
 
2188
 
 
2189
    unsigned int _crc32;
 
2190
 
 
2191
    bool _bound;
 
2192
    bool _placeholder;
 
2193
 
 
2194
    bool _watch_lists; //< adds the virtual method that's called when owned lists are changed (watch-lists)
 
2195
    bool _watch_dicts; //< adds the virtual method that's called when owned dicts are changed (watch-dicts)
 
2196
    bool _force_impl;
 
2197
    bool _impl_data;  //< needs extra data for the object
 
2198
  };
 
2199
  
 
2200
  
 
2201
  //------------------------------------------------------------------------------------------------
 
2202
  //------------------------------------------------------------------------------------------------
 
2203
  
 
2204
  class Module;
 
2205
  class Interface;
 
2206
 
 
2207
  /** Module loader base class.
 
2208
   * 
 
2209
   * Supports loading and execution of modules composed of functions written in
 
2210
   * a language. @a CPPModuleLoader is a special module loader to handle modules
 
2211
   * written in C++.
 
2212
   * 
 
2213
   * @ingroup GRT
 
2214
   */
 
2215
  class MYSQLGRT_PUBLIC ModuleLoader
 
2216
  {
 
2217
  public:
 
2218
    ModuleLoader(GRT *grt) : _grt(grt) {}
 
2219
    virtual ~ModuleLoader() {}
 
2220
 
 
2221
    virtual std::string get_loader_name()= 0;
 
2222
 
 
2223
    virtual Module *init_module(const std::string &path)= 0;
 
2224
 
 
2225
    virtual void refresh()= 0;
 
2226
 
 
2227
    virtual bool load_library(const std::string &path)= 0;
 
2228
    virtual bool run_script_file(const std::string &path)= 0;
 
2229
    virtual bool run_script(const std::string &script)= 0;
 
2230
    virtual bool check_file_extension(const std::string &path)= 0;
 
2231
    
 
2232
    GRT *get_grt() const { return _grt; }
 
2233
    
 
2234
  protected:
 
2235
    GRT *_grt; //TODO: make it private, get_grt is as fast as direct access
 
2236
  };
 
2237
 
 
2238
 
 
2239
  /** A GRT module class.
 
2240
   * 
 
2241
   * This class may be subclassed to create C++ modules. 
 
2242
   * A C++ module may be called directly through its @a Module
 
2243
   * object or indirectly, through a @a ModuleWrapper
 
2244
   * 
 
2245
   * @ingroup GRT
 
2246
   */ 
 
2247
  class LuaModuleLoader;
 
2248
  class MYSQLGRT_PUBLIC Module//
 
2249
  {
 
2250
  friend class LuaModuleLoader;
 
2251
  public:
 
2252
    struct Function
 
2253
    {
 
2254
      std::string name;
 
2255
      std::string description;
 
2256
      TypeSpec ret_type;
 
2257
      ArgSpecList arg_types;
 
2258
 
 
2259
      boost::function<ValueRef (const grt::BaseListRef&)> call;
 
2260
    };
 
2261
 
 
2262
    bool has_function(const std::string &name) const;
 
2263
    virtual ValueRef call_function(const std::string &name, const grt::BaseListRef &args);
 
2264
 
 
2265
    Module(ModuleLoader *loader);
 
2266
    virtual ~Module() {}
 
2267
 
 
2268
    std::string name() const { return _name; }
 
2269
    std::string version() const { return _meta_version; }
 
2270
    std::string author() const { return _meta_author; }
 
2271
    std::string description() const { return _meta_description; }
 
2272
    std::string extends() const { return _extends; }
 
2273
    std::string path() const { return _path; }
 
2274
    std::string bundle_path() const;
 
2275
    std::string default_icon_path() const;
 
2276
 
 
2277
    bool is_bundle() const { return _is_bundle; }
 
2278
 
 
2279
    const std::vector<Function> &get_functions() const { return _functions; }
 
2280
    
 
2281
    const Function *get_function(const std::string &name) const;
 
2282
    
 
2283
    typedef std::vector<std::string> Interfaces;
 
2284
 
 
2285
    //! Returns list of the interfaces which Module implements    
 
2286
    const Interfaces &get_interfaces() const { return _interfaces; }
 
2287
 
 
2288
    ModuleLoader *get_loader() const { return _loader; }
 
2289
    GRT *get_grt() const { return _loader->get_grt(); }
 
2290
 
 
2291
    void validate() const;
 
2292
 
 
2293
    
 
2294
    void set_global_data(const std::string &key, const std::string &value);
 
2295
    void set_global_data(const std::string &key, int value);
 
2296
    int global_int_data(const std::string &key, int default_value= 0);
 
2297
    std::string global_string_data(const std::string &key, const std::string &default_value= "");
 
2298
 
 
2299
    void set_document_data(const std::string &key, const std::string &value);
 
2300
    void set_document_data(const std::string &key, int value);
 
2301
    int document_int_data(const std::string &key, int default_value= 0);
 
2302
    std::string document_string_data(const std::string &key, const std::string &default_value= "");
 
2303
 
 
2304
  protected:
 
2305
    
 
2306
    /** Parse a String defined module function specification.
 
2307
     * 
 
2308
     * Function parameter list syntax:
 
2309
     * @code
 
2310
     * param_list::= param[, param_list]
 
2311
     * param::= type [ label]
 
2312
     * label::= a name for the parameter
 
2313
     * type::= i | r | s | l[<content_spec>] | d[<content_spec>] | o[@struct]
 
2314
     * content_spec::= i | r | s | o@struct
 
2315
     * struct::= name of a valid struct
 
2316
     * @endcode
 
2317
     *
 
2318
     * Ex.:
 
2319
     *  doSomething:s:i count,l<i> poslist,o<db.mysql.Table> table,d args
 
2320
     */
 
2321
    virtual bool add_parse_function_spec(const std::string &spec, const boost::function<ValueRef (BaseListRef, Module*, Module::Function)> &caller);
 
2322
    
 
2323
    void add_function(const Function &func);
 
2324
 
 
2325
    std::string _name;
 
2326
    std::string _path;
 
2327
 
 
2328
    std::string _meta_version;
 
2329
    std::string _meta_author;
 
2330
    std::string _meta_description;
 
2331
 
 
2332
    std::vector<Function> _functions;
 
2333
 
 
2334
    std::string _extends;
 
2335
    //Module *_extends;
 
2336
    Interfaces _interfaces; 
 
2337
 
 
2338
    bool _is_bundle;
 
2339
 
 
2340
    ModuleLoader *_loader;
 
2341
  };
 
2342
 
 
2343
 
 
2344
  /** Base class for module wrapper classes.
 
2345
   * 
 
2346
   * This class is inherited by classes automatically generated by the genwrap tool.
 
2347
   * These wrapper classes expose GRT modules written in any language as a C++ object.
 
2348
   * 
 
2349
   * @ingroup GRT
 
2350
  */
 
2351
  class MYSQLGRT_PUBLIC ModuleWrapper
 
2352
  {
 
2353
  public:
 
2354
    ModuleWrapper(Module *module) : _module(module) {}
 
2355
    virtual ~ModuleWrapper() {}
 
2356
 
 
2357
    Module *get_module() const { return _module; }
 
2358
    GRT *get_grt() const { return _module->get_grt(); }
 
2359
    
 
2360
  protected:
 
2361
    Module *_module;
 
2362
  };
 
2363
  
 
2364
 
 
2365
  //------------------------------------------------------------------------------------------------
 
2366
  //------------------------------------------------------------------------------------------------
 
2367
 
 
2368
  typedef enum {
 
2369
    ErrorMsg,
 
2370
    WarningMsg,
 
2371
    InfoMsg,
 
2372
    OutputMsg,
 
2373
    VerboseMsg,
 
2374
    ProgressMsg = 10,
 
2375
 
 
2376
    ControlMsg = 1000,
 
2377
    NoErrorMsg = 0x1000 //!< NoErrorMsg is used for live validation. ValidationManager uses this message type to 
 
2378
                        //!< inform listeners that certain UI (list of errors, etc..) should be cleared
 
2379
  } MessageType;
 
2380
 
 
2381
 
 
2382
  struct MYSQLGRT_PUBLIC Message
 
2383
  {
 
2384
    MessageType type;
 
2385
    time_t timestamp;
 
2386
    std::string text;
 
2387
    std::string detail;
 
2388
    float progress;
 
2389
    
 
2390
    std::string format(bool withtype= false) const;
 
2391
  };
 
2392
 
 
2393
  typedef boost::function<void (const Message&, void*)> MessageSlot;
 
2394
  typedef boost::function<bool ()> StatusQuerySlot;
 
2395
 
 
2396
  //-----------------------------------------------------------------------------------------------
 
2397
  
 
2398
  // gcc and msc produce different output for typeid(arg).name()
 
2399
  // this function is a platform independent wrapper for typeid(arg).name() 
 
2400
  inline std::string get_full_type_name(const std::type_info& ti)
 
2401
  {
 
2402
#ifdef __GNUC__
 
2403
    int s;
 
2404
    char *tmp= __cxxabiv1::__cxa_demangle(ti.name(), NULL, NULL, &s);
 
2405
    std::string ret(tmp);
 
2406
    free(tmp);
 
2407
    return ret;
 
2408
#elif _MSC_VER
 
2409
    const char *name= ti.name();
 
2410
    if(strncmp("class ", name, sizeof("class ") - 1) == 0)
 
2411
      return std::string(name + sizeof("class ") - 1);
 
2412
    else if(strncmp("struct ", name, sizeof("struct ") - 1) == 0)
 
2413
      return std::string(name + sizeof("struct ") - 1);
 
2414
    else
 
2415
      return std::string(name);
 
2416
#else
 
2417
# error Unknown compiler
 
2418
#endif
 
2419
  }
 
2420
 
 
2421
  inline std::string get_type_name(const std::type_info& ti)
 
2422
  {
 
2423
    std::string name= get_full_type_name(ti);
 
2424
 
 
2425
    // strip namespace:: 
 
2426
    std::string::size_type p= name.rfind(':');
 
2427
    if (p != std::string::npos)
 
2428
      return name.substr(p+1);
 
2429
 
 
2430
    return name;
 
2431
  }
 
2432
 
 
2433
  //------------------------------------------------------------------------------------------------
 
2434
  //------------------------------------------------------------------------------------------------
 
2435
 
 
2436
  class UndoManager;
 
2437
  class Shell;
 
2438
  class ModuleWrapper;
 
2439
  class CPPModuleLoader;
 
2440
  class Interface;
 
2441
  
 
2442
  class UndoGroup;
 
2443
 
 
2444
  /** The main GRT context object.
 
2445
   * 
 
2446
   * @ingroup GRT
 
2447
   */ 
 
2448
  class MYSQLGRT_PUBLIC GRT//
 
2449
  {
 
2450
  public:
 
2451
    GRT();
 
2452
    ~GRT();
 
2453
    /** 
 
2454
     *
 
2455
     * @param flag  
 
2456
     *
 
2457
     * @return 
 
2458
     */
 
2459
    void set_verbose(bool flag);
 
2460
    bool verbose() const { return _verbose; }
 
2461
    
 
2462
    // metaclasss
 
2463
    
 
2464
    /** Load metaclasses defined in a XML file.
 
2465
     * 
 
2466
     * @ref end_loading_metaclasses() must be called once no more metaclasses
 
2467
     * will be loaded.
 
2468
     * 
 
2469
     * @param requires list of other XML files required by the loaded one
 
2470
     */
 
2471
    void load_metaclasses(const std::string &file, std::list<std::string> *requires= 0);
 
2472
    /** Scans a directory for metaclass definition files and load them.
 
2473
     * Looks in the directory for files with the structs*.xml pattern and loads metaclasses
 
2474
     * defined in them. The list of other struct files pre-required is returned in the optional
 
2475
     * @a requires parameter.
 
2476
     * 
 
2477
     * @ref end_loading_metaclasses() must be called once no more metaclasses
 
2478
     * will be loaded.
 
2479
     * 
 
2480
     * @param dir directory to look for struct files
 
2481
     * @param requires optional pointer to a multimap where required XML files for each loaded
 
2482
     * files is stored
 
2483
     */
 
2484
    int scan_metaclasses_in(const std::string &dir, std::multimap<std::string,std::string> *requires= 0);
 
2485
    /** End loading of metaclass definition files.
 
2486
     * Finishes up loading of metaclass definition XMLs files. This will
 
2487
     * check that all metaclasses referred by something were loaded. It will
 
2488
     * also perform initialization of all known implementatin classes by
 
2489
     * binding properties and method pointers.
 
2490
     */
 
2491
    void end_loading_metaclasses(bool check_class_binding=true);
 
2492
    
 
2493
    const std::list<MetaClass*>& get_metaclasses() const { return _metaclasses_list; }
 
2494
 
 
2495
    MetaClass *get_metaclass(const std::string &name) const;
 
2496
 
 
2497
    template<class C>
 
2498
      Ref<C> create_object(const std::string &class_name) const
 
2499
    {
 
2500
      MetaClass *mc= get_metaclass(class_name);
 
2501
      if (!mc) throw bad_class(class_name);
 
2502
      return Ref<C>::cast_from(mc->allocate());
 
2503
    }
 
2504
 
 
2505
    //serialization    
 
2506
    void serialize(const ValueRef &value, const std::string &path, 
 
2507
                   const std::string &doctype="", const std::string &version="",
 
2508
                   bool list_objects_as_links= false);
 
2509
    ValueRef unserialize(const std::string &path);
 
2510
    ValueRef unserialize(const std::string &path, std::string &doctype_ret, std::string &version_ret);
 
2511
 
 
2512
    xmlDocPtr load_xml(const std::string &path);
 
2513
    void get_xml_metainfo(xmlDocPtr doc, std::string &doctype_ret, std::string &version_ret);
 
2514
    ValueRef unserialize_xml(xmlDocPtr doc, const std::string &source_path);
 
2515
 
 
2516
    std::string serialize_xml_data(const ValueRef &value, const std::string &doctype="", 
 
2517
      const std::string &version="", bool list_objects_as_links= false);
 
2518
    ValueRef unserialize_xml_data(const std::string &data);
 
2519
 
 
2520
    
 
2521
    // globals
 
2522
    
 
2523
    inline ValueRef root() const { return _root; }
 
2524
    void set_root(const ValueRef &root);
 
2525
    
 
2526
    ValueRef get(const std::string &path) const;
 
2527
    void set(const std::string &path, const ValueRef &value);
 
2528
    
 
2529
    ObjectRef find_object_by_id(const std::string &id, const std::string &subpath);
 
2530
 
 
2531
 
 
2532
    // modules
 
2533
    
 
2534
    // path in globals tree for modules to store options
 
2535
    void set_global_module_data_path(const std::string &path) { _global_module_options_path= path; }
 
2536
    std::string global_module_data_path() { return _global_module_options_path; }
 
2537
 
 
2538
    void set_document_module_data_path(const std::string &path) { _document_module_options_path= path; }
 
2539
    std::string document_module_data_path() { return _document_module_options_path; }
 
2540
 
 
2541
    void add_module_loader(ModuleLoader *loader);
 
2542
    bool load_module(const std::string &path, bool refresh);
 
2543
    void end_loading_modules();
 
2544
     
 
2545
    ModuleLoader *get_module_loader(const std::string &name);
 
2546
    ModuleLoader *get_module_loader_for_file(const std::string &path);
 
2547
    void refresh_loaders();
 
2548
 
 
2549
    void register_new_module(Module *module);
 
2550
    void refresh_module(Module *module);
 
2551
    void unregister_module(Module *module);
 
2552
 
 
2553
    void register_new_interface(Interface *iface);
 
2554
    const std::map<std::string,Interface*> &get_interfaces() const { return _interfaces; }
 
2555
    const Interface *get_interface(const std::string &name);
 
2556
    
 
2557
    int scan_modules_in(const std::string &path, const std::list<std::string> &exts,
 
2558
                        bool reload);
 
2559
    
 
2560
    const std::vector<Module*> &get_modules() const { return _modules; }
 
2561
    
 
2562
    Module *get_module(const std::string &name);
 
2563
    
 
2564
    // create an instance of the given native module and registers it with the GRT.
 
2565
    // this should not be used for accessing modules, use the
 
2566
    // wrapper class for the module you want, instead (with get_module())
 
2567
    template<class ModuleImplClass>
 
2568
      ModuleImplClass *get_native_module()
 
2569
      {
 
2570
        std::string mname= get_type_name(typeid(ModuleImplClass));
 
2571
        Module *module;
 
2572
 
 
2573
        if (mname.size() > 4 && mname.substr(mname.size()-4)=="Impl")
 
2574
          mname= mname.substr(0, mname.size()-4);
 
2575
 
 
2576
        ModuleImplClass *instance;
 
2577
 
 
2578
        module= get_module(mname);
 
2579
        if (!module)
 
2580
        {
 
2581
          instance= new ModuleImplClass((CPPModuleLoader*)get_module_loader("cpp"));
 
2582
          instance->init_module();
 
2583
          register_new_module(instance);
 
2584
        }
 
2585
        else
 
2586
        {
 
2587
          instance= dynamic_cast<ModuleImplClass*>(module);
 
2588
          if (!instance)
 
2589
            return 0;
 
2590
        }
 
2591
 
 
2592
        return instance;
 
2593
      }
 
2594
 
 
2595
    // locate an instance of a module. suitable for direct access to modules
 
2596
    template<class ModuleImplClass>
 
2597
      ModuleImplClass *find_native_module(const char *name)
 
2598
      {
 
2599
        Module *module= get_module(name);
 
2600
 
 
2601
        return static_cast<ModuleImplClass*>(module);
 
2602
      }
 
2603
 
 
2604
    std::vector<Module*> find_modules_matching(const std::string &interface_name, const std::string &name_pattern);
 
2605
 
 
2606
    template<class InterfaceWrapperClass>
 
2607
      std::vector<InterfaceWrapperClass*> get_implementing_modules()
 
2608
    {
 
2609
      std::vector<Module*> modules;
 
2610
      std::vector<InterfaceWrapperClass*> mlist;
 
2611
 
 
2612
      modules= find_modules_matching(InterfaceWrapperClass::static_get_name(), "");
 
2613
 
 
2614
      for (std::vector<Module*>::const_iterator i= modules.begin();
 
2615
           i != modules.end(); ++i)
 
2616
      {
 
2617
        mlist.push_back(get_module_wrapper<InterfaceWrapperClass>(*i));
 
2618
      }
 
2619
 
 
2620
      return mlist;
 
2621
    }
 
2622
 
 
2623
    // create an instance of a wrapper for the given module
 
2624
    template<class ModuleWrapperClass>
 
2625
      ModuleWrapperClass *get_module_wrapper(Module *amodule)
 
2626
      {
 
2627
        ModuleWrapper *bmodule= _cached_module_wrapper[std::string(ModuleWrapperClass::static_get_name()).append("/").append(amodule->name())];
 
2628
        ModuleWrapperClass *wrapper= dynamic_cast<ModuleWrapperClass*>(bmodule);
 
2629
 
 
2630
        if (!wrapper)
 
2631
        {
 
2632
          wrapper= new ModuleWrapperClass(amodule);
 
2633
          _cached_module_wrapper[std::string(ModuleWrapperClass::static_get_name()).append("/").append(amodule->name())]= wrapper;
 
2634
        }
 
2635
        return wrapper;
 
2636
      }
 
2637
 
 
2638
    template<class ModuleWrapperClass>
 
2639
       ModuleWrapperClass *get_module_wrapper(const std::string &module)
 
2640
      {
 
2641
        ModuleWrapper *bmodule= _cached_module_wrapper[std::string(ModuleWrapperClass::static_get_name()).append("/").append(module)];
 
2642
        ModuleWrapperClass *wrapper= dynamic_cast<ModuleWrapperClass*>(bmodule);
 
2643
 
 
2644
        if (!wrapper)
 
2645
        {
 
2646
          Module *amodule= get_module(module);
 
2647
          if (amodule)
 
2648
          {
 
2649
            wrapper= new ModuleWrapperClass(amodule);
 
2650
            _cached_module_wrapper[std::string(ModuleWrapperClass::static_get_name()).append("/").append(amodule->name())]= wrapper;
 
2651
          }
 
2652
        }
 
2653
        return wrapper;
 
2654
      }
 
2655
 
 
2656
    
 
2657
    // context data
 
2658
 
 
2659
    void set_context_data(const std::string &key, void *value, void(*free_value)(void*)= 0);
 
2660
    void unset_context_data(const std::string &key);
 
2661
    void *get_context_data(const std::string &key);
 
2662
    
 
2663
 
 
2664
    // shell
 
2665
    bool init_shell(const std::string &shell_type);
 
2666
    Shell *get_shell();
 
2667
    std::string shell_type();
 
2668
 
 
2669
    // undo tracking
 
2670
    void push_undo_manager(UndoManager *um);
 
2671
    UndoManager *pop_undo_manager();
 
2672
 
 
2673
    UndoManager *get_undo_manager() const;
 
2674
    void start_tracking_changes();
 
2675
    void stop_tracking_changes();
 
2676
    bool tracking_changes() const { return _tracking_changes > 0; }
 
2677
 
 
2678
    /** Starts tracking undo changes and opens an undo group.
 
2679
     * Use the AutoUndo class for auto-trackign.
 
2680
     */
 
2681
    UndoGroup *begin_undoable_action(UndoGroup *group= 0);
 
2682
    void end_undoable_action(const std::string &group_description);
 
2683
    void cancel_undoable_action();
 
2684
 
 
2685
 
 
2686
    // grt logging/messaging
 
2687
    MessageSlot set_message_handler(const MessageSlot &slot);
 
2688
    StatusQuerySlot set_status_query_handler(const StatusQuerySlot &slot);
 
2689
     
 
2690
    void make_output_visible(void *sender= NULL);
 
2691
 
 
2692
    void send_error(const std::string &message, const std::string &details="", void *sender= NULL);
 
2693
    void send_warning(const std::string &message, const std::string &details="", void *sender= NULL);
 
2694
    void send_info(const std::string &message, const std::string &details="", void *sender= NULL);
 
2695
    void send_progress(float percentage, const std::string &message, const std::string &details="", void *sender= NULL);
 
2696
 
 
2697
    void send_verbose(const std::string &message, void *sender= NULL);
 
2698
    void send_output(const std::string &text, void *sender= NULL);
 
2699
 
 
2700
  protected:
 
2701
    struct AutoLock
 
2702
    {
 
2703
      const GRT *_grt;
 
2704
      AutoLock(const GRT *grt) : _grt(grt) { _grt->lock(); }
 
2705
      ~AutoLock() { _grt->unlock(); }
 
2706
    };
 
2707
    void lock() const;
 
2708
    void unlock() const;
 
2709
 
 
2710
  protected:
 
2711
    friend class MetaClass;
 
2712
 
 
2713
    //std::map<std::string,internal::Object*> _objects;
 
2714
 
 
2715
    MessageSlot _message_slot;
 
2716
    StatusQuerySlot _status_query_slot;
 
2717
 
 
2718
    GStaticRecMutex _message_mutex;
 
2719
 
 
2720
    std::list<ModuleLoader*> _loaders;
 
2721
    std::vector<Module*> _modules;
 
2722
    std::map<std::string,Interface*> _interfaces;
 
2723
    std::map<std::string,ModuleWrapper*> _cached_module_wrapper;
 
2724
 
 
2725
    std::map<std::string, std::pair<void*,void(*)(void*)> > _context_data;
 
2726
 
 
2727
    Shell *_shell;
 
2728
    
 
2729
    //std::list<ModuleLoader*> _loaders;
 
2730
    
 
2731
    // GStaticRecMutex _global_mutex;
 
2732
    // GStaticRWLock _global_tree_lock;
 
2733
 
 
2734
    void add_metaclass(MetaClass *stru);
 
2735
    std::string module_path_in_bundle(const std::string &path);
 
2736
 
 
2737
    std::map<std::string,MetaClass*> _metaclasses;
 
2738
    std::list<MetaClass*> _metaclasses_list;
 
2739
 
 
2740
    ValueRef _root;
 
2741
    std::list<UndoManager*> _undo_managers;
 
2742
    UndoManager *_default_undo_manager;
 
2743
    std::string _global_module_options_path;
 
2744
    std::string _document_module_options_path;
 
2745
    int _tracking_changes;
 
2746
    bool _check_serialized_crc;
 
2747
    bool _verbose;
 
2748
    bool _scanning_modules;
 
2749
  };
 
2750
  
 
2751
  //------------------------------------------------------------------------------------------------
 
2752
  //------------------------------------------------------------------------------------------------
 
2753
 
 
2754
  template<class O>
 
2755
  inline bool ListRef<O>::can_wrap(const ValueRef &value)
 
2756
  { 
 
2757
    if (value.type() != ListType)
 
2758
      return false;
 
2759
    
 
2760
    if (!value.is_valid())
 
2761
      return true;
 
2762
 
 
2763
    internal::List *candidate_list= static_cast<internal::List*>(value.valueptr());
 
2764
 
 
2765
    if (candidate_list->content_type() != O::static_type())
 
2766
      return false;
 
2767
 
 
2768
    // we allow stuff like List<db_Table> = List<db_mysql_Table>
 
2769
    // 
 
2770
    MetaClass *content_class= candidate_list->get_grt()->get_metaclass(O::static_class_name());
 
2771
    if (!content_class && !O::static_class_name().empty())
 
2772
      throw std::runtime_error(std::string("metaclass without runtime info ").append(O::static_class_name()));
 
2773
 
 
2774
    MetaClass *candidate_class= candidate_list->get_grt()->get_metaclass(candidate_list->content_class_name());
 
2775
    if (!candidate_class && !candidate_list->content_class_name().empty())
 
2776
      throw std::runtime_error(std::string("metaclass without runtime info ").append(candidate_list->content_class_name()));
 
2777
 
 
2778
    if (candidate_class == content_class) // classes are the same
 
2779
      return true;
 
2780
    if (!content_class) // we're a generic list
 
2781
      return true;
 
2782
    if (!candidate_class) // candidate is a generic list and we're not
 
2783
      return false;
 
2784
    return candidate_class->is_a(content_class);
 
2785
  }
 
2786
 
 
2787
};
 
2788
 
 
2789
#endif