BEAST/BSE - Better Audio System and Sound Engine  0.8.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
sficxx.hh
Go to the documentation of this file.
00001  // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
00002 #ifndef __SFI_CXX_H__
00003 #define __SFI_CXX_H__
00004 #include <sfi/sfi.hh>
00005 #include <string>
00006 #include <string.h>
00007 #include <new>
00008 
00010 namespace Sfi {
00011 typedef SfiBool   Bool;    // FIXME: use bool instead?
00012 typedef SfiInt    Int;
00013 typedef SfiNum    Num;
00014 typedef SfiReal   Real;
00015 class String {
00016   char *cstring;
00017   int cmp (const char *ostring) const
00018   {
00019     if (cstring && ostring)
00020       return strcmp (cstring, ostring);
00021     else if (cstring)
00022       return +SFI_MAXINT;
00023     else
00024       return ostring ? SFI_MININT : 0;
00025   }
00026 public:
00027   String()
00028   {
00029     cstring = g_strdup ("");
00030   }
00031   String (const String &s)
00032   {
00033     cstring = g_strdup (s.cstring);
00034   }
00035   String (const std::string &s)
00036   {
00037     cstring = g_strdup (s.c_str());
00038   }
00039   String (const char *cstr)
00040   {
00041     cstring = g_strdup (cstr ? cstr : "");
00042   }
00043   String& operator= (const std::string &s)
00044   {
00045     g_free (cstring);
00046     cstring = g_strdup (s.c_str());
00047     return *this;
00048   }
00049   String& operator= (const gchar *cstr)
00050   {
00051     if (cstr != cstring)
00052       {
00053         g_free (cstring);
00054         cstring = g_strdup (cstr ? cstr : "");
00055       }
00056     return *this;
00057   }
00058   String& operator= (const String &s)
00059   {
00060     if (s.cstring != cstring)
00061       {
00062         g_free (cstring);
00063         cstring = g_strdup (s.cstring);
00064       }
00065     return *this;
00066   }
00067   const char* c_str() const
00068   {
00069     return cstring;
00070   }
00071   String& operator+= (const gchar *cstr)
00072   {
00073     char *old = cstring;
00074     cstring = g_strconcat (old ? old : "", cstr, NULL);
00075     g_free (old);
00076     return *this;
00077   }
00078   String& operator+= (const String &src)
00079   {
00080     char *old = cstring;
00081     cstring = g_strconcat (old ? old : "", src.cstring, NULL);
00082     g_free (old);
00083     return *this;
00084   }
00085   String& operator+= (const std::string &src)
00086   {
00087     char *old = cstring;
00088     cstring = g_strconcat (old ? old : "", src.c_str(), NULL);
00089     g_free (old);
00090     return *this;
00091   }
00092   String operator+ (const gchar *cstr)
00093   {
00094     return String (cstring) += cstr;
00095   }
00096   String operator+ (const String &src)
00097   {
00098     return String (cstring) += src;
00099   }
00100   String operator+ (const std::string &src)
00101   {
00102     return String (cstring) += src;
00103   }
00104   bool operator<  (const char *src) const { return cmp (src) < 0; }
00105   bool operator<= (const char *src) const { return cmp (src) <= 0; }
00106   bool operator>  (const char *src) const { return cmp (src) > 0; }
00107   bool operator>= (const char *src) const { return cmp (src) >= 0; }
00108   bool operator!= (const char *src) const { return cmp (src) != 0; }
00109   bool operator== (const char *src) const { return cmp (src) == 0; }
00110   bool operator<  (const String &s) const { return cmp (s.cstring) < 0; }
00111   bool operator<= (const String &s) const { return cmp (s.cstring) <= 0; }
00112   bool operator>  (const String &s) const { return cmp (s.cstring) > 0; }
00113   bool operator>= (const String &s) const { return cmp (s.cstring) >= 0; }
00114   bool operator!= (const String &s) const { return cmp (s.cstring) != 0; }
00115   bool operator== (const String &s) const { return cmp (s.cstring) == 0; }
00116   bool operator<  (const std::string &s) const { return cmp (s.c_str()) < 0; }
00117   bool operator<= (const std::string &s) const { return cmp (s.c_str()) <= 0; }
00118   bool operator>  (const std::string &s) const { return cmp (s.c_str()) > 0; }
00119   bool operator>= (const std::string &s) const { return cmp (s.c_str()) >= 0; }
00120   bool operator!= (const std::string &s) const { return cmp (s.c_str()) != 0; }
00121   bool operator== (const std::string &s) const { return cmp (s.c_str()) == 0; }
00122   unsigned int length()
00123   {
00124     return cstring ? strlen (cstring) : 0;
00125   }
00126   ~String()
00127   {
00128     g_free (cstring);
00129   }
00130   /* provide GValue accessors */
00131   static String value_get_string (const GValue *value)
00132   {
00133     return sfi_value_get_string (value);
00134   }
00135   static void value_set_string (GValue       *value,
00136                                 const String& str)
00137   {
00138     sfi_value_set_string (value, str.c_str());
00139   }
00140 };
00141 
00142 struct GNewable {
00143   gpointer operator new (size_t s)
00144   {
00145     return g_malloc0 (s);
00146   }
00147   void operator delete (gpointer mem)
00148   {
00149     g_free (mem);
00150   }
00151   gpointer operator new[] (size_t s)
00152   {
00153     return g_malloc0 (s);
00154   }
00155   void operator delete[] (gpointer mem)
00156   {
00157     g_free (mem);
00158   }
00159 };
00160 
00161 typedef enum {
00162   INIT_NULL,
00163   INIT_EMPTY,
00164   INIT_DEFAULT,
00165 } InitializationType;
00166 
00167 template<typename Type>
00168 class RecordHandle {
00169   Type *record;
00170   typedef Type BoxedType;
00171 public:
00172   RecordHandle (InitializationType t = INIT_NULL)
00173   {
00174     record = NULL;
00175     if (t == INIT_DEFAULT || t == INIT_EMPTY)
00176       record = new Type();
00177   }
00178   RecordHandle (const RecordHandle &rh)
00179   {
00180     if (rh.record)
00181       record = new Type (*rh.record);
00182     else
00183       record = NULL;
00184   }
00185   RecordHandle (const Type &rec)
00186   {
00187     record = new Type (rec);
00188   }
00189   RecordHandle& operator= (const Type &rec)
00190   {
00191     if (record != &rec)
00192       {
00193         delete record;
00194         record = new Type (rec);
00195       }
00196     return *this;
00197   }
00198   void set_boxed (Type *rec)
00199   {
00200     delete record;
00201     if (rec)
00202       record = new Type (*rec);
00203     else
00204       record = NULL;
00205   }
00206   void take (Type *rec)
00207   {
00208     delete record;
00209     record = rec;
00210   }
00211   Type* steal ()
00212   {
00213     Type *t = record;
00214     record = NULL;
00215     return t;
00216   }
00217   Type* c_ptr() const
00218   {
00219     return record;
00220   }
00221   RecordHandle& operator= (const RecordHandle &src)
00222   {
00223     if (record != src.record)
00224       {
00225         delete record;
00226         if (src.record)
00227           record = new Type (*src.record);
00228         else
00229           record = NULL;
00230       }
00231     return *this;
00232   }
00233   ~RecordHandle()
00234   {
00235     delete record;
00236   }
00237   Type*
00238   operator-> ()
00239   {
00240     return record;
00241   }
00242   const Type*
00243   operator-> () const
00244   {
00245     return record;
00246   }
00247   Type&
00248   operator* ()
00249   {
00250     return *record;
00251   }
00252   const Type&
00253   operator* () const
00254   {
00255     return *record;
00256   }
00257   Type& operator[] (unsigned int index)
00258   {
00259     if (index)
00260       g_critical ("%s: invalid array subscript: %u", G_STRFUNC, index);
00261     return *(index ? NULL : record);
00262   }
00263   bool is_null() const
00264   {
00265     return !record;
00266   }
00267   operator bool () const
00268   {
00269     return !is_null();
00270   }
00271   static gpointer
00272   boxed_copy (gpointer data)
00273   {
00274     if (data)
00275       {
00276         Type *r = reinterpret_cast<Type*> (data);
00277         RecordHandle rh (*r);
00278         return rh.steal();
00279       }
00280     return NULL;
00281   }
00282   static void
00283   boxed_free (gpointer data)
00284   {
00285     if (data)
00286       {
00287         Type *r = reinterpret_cast<Type*> (data);
00288         RecordHandle rh;
00289         rh.take (r);
00290       }
00291   }
00292   static RecordHandle
00293   value_get_boxed (const GValue *value)
00294   {
00295     if (SFI_VALUE_HOLDS_REC (value))
00296       {
00297         SfiRec *rec = sfi_value_get_rec (value);
00298         RecordHandle rh = Type::from_rec (rec);
00299         return rh;
00300       }
00301     else
00302       {
00303         Type *boxed = reinterpret_cast<Type*> (g_value_get_boxed (value));
00304         if (boxed)
00305           return *boxed;
00306         else
00307           return INIT_NULL;
00308       }
00309   }
00310   static void
00311   value_set_boxed (GValue             *value,
00312                    const RecordHandle &self)
00313   {
00314     if (SFI_VALUE_HOLDS_REC (value))
00315       {
00316         SfiRec *rec = Type::to_rec (self);
00317         sfi_value_take_rec (value, rec);
00318       }
00319     else
00320       g_value_set_boxed (value, self.c_ptr());
00321   }
00322 };
00323 
00324 template<typename Type>
00325 class Sequence {
00326 public:
00327   typedef Type*       iterator;
00328   typedef const Type* const_iterator;
00329   struct CSeq {
00330     unsigned int n_elements;
00331     Type        *elements;
00332   };
00333   typedef CSeq BoxedType;
00334 private:
00335   CSeq *cseq;
00336 public:
00337   Sequence (unsigned int n = 0)
00338   {
00339     cseq = g_new0 (CSeq, 1);
00340     resize (n);
00341   }
00342   Sequence (const Sequence &sh)
00343   {
00344     cseq = g_new0 (CSeq, 1);
00345     *this = sh;
00346   }
00347   Sequence (const BoxedType &cs)
00348   {
00349     cseq = g_new0 (CSeq, 1);
00350     set_boxed (&cs);
00351   }
00352   iterator
00353   begin()
00354   {
00355     return cseq->elements;
00356   }
00357   const_iterator
00358   begin() const
00359   {
00360     return cseq->elements;
00361   }
00362   iterator
00363   end()
00364   {
00365     return cseq->elements + cseq->n_elements;
00366   }
00367   const_iterator
00368   end() const
00369   {
00370     return cseq->elements + cseq->n_elements;
00371   }
00372   void
00373   take (CSeq *cs)
00374   {
00375     resize (0);
00376     if (cs)
00377       {
00378         g_free (cseq->elements);
00379         g_free (cseq);
00380         cseq = cs;
00381         /* a take(); steal(); sequence needs to preserve pointer */
00382       }
00383   }
00384   CSeq*
00385   steal ()
00386   {
00387     CSeq *cs = cseq;
00388     cseq = g_new0 (CSeq, 1);
00389     resize (0);
00390     /* a take(); steal(); sequence needs to preserve pointer */
00391     return cs;
00392   }
00393   CSeq*
00394   c_ptr() const
00395   {
00396     return cseq;
00397   }
00398   void
00399   resize (unsigned int n)
00400   {
00401     guint i;
00402     // Note that this does *not* use an explicit copy-constructor call to relocate existing elements
00403     for (i = n; i < length(); i++)
00404       cseq->elements[i].~Type();
00405     i = cseq->n_elements;
00406     cseq->n_elements = n;
00407     cseq->elements = g_renew (Type, cseq->elements, cseq->n_elements);
00408     for (; i < length(); i++)
00409       new (cseq->elements + i) Type ();
00410   }
00411   Type&
00412   operator[] (unsigned int index)
00413   {
00414     if (index >= cseq->n_elements)
00415       g_critical ("%s: invalid array subscript: %u", G_STRFUNC, index);
00416     return cseq->elements[index];
00417   }
00418   const Type&
00419   operator[] (unsigned int index) const
00420   {
00421     if (index >= cseq->n_elements)
00422       g_critical ("%s: invalid array subscript: %u", G_STRFUNC, index);
00423     return cseq->elements[index];
00424   }
00425   Sequence&
00426   operator+= (const Type &elm)
00427   {
00428     // Note that this does *not* use an explicit copy-constructor call to relocate existing elements
00429     guint i = cseq->n_elements++;
00430     cseq->elements = g_renew (Type, cseq->elements, cseq->n_elements);
00431     new (cseq->elements + i) Type (elm);
00432     return *this;
00433   }
00434   void
00435   set_boxed (const CSeq *cs)
00436   {
00437     if (cseq == cs)
00438       return;
00439     resize (0);
00440     if (!cs)
00441       return;
00442     cseq->n_elements = cs->n_elements;
00443     cseq->elements = g_renew (Type, cseq->elements, cseq->n_elements);
00444     for (guint i = 0; i < length(); i++)
00445       new (cseq->elements + i) Type (cs->elements[i]);
00446   }
00447   Sequence&
00448   operator= (const Sequence &sh)
00449   {
00450     set_boxed (sh.cseq);
00451     return *this;
00452   }
00453   unsigned int
00454   length() const
00455   {
00456     return cseq ? cseq->n_elements : 0;
00457   }
00458   ~Sequence()
00459   {
00460     resize (0);
00461     g_free (cseq->elements);
00462     g_free (cseq);
00463   }
00464   static gpointer
00465   boxed_copy (gpointer data)
00466   {
00467     if (data)
00468       {
00469         CSeq *cs = reinterpret_cast<CSeq*> (data);
00470         Sequence s (*cs);
00471         return s.steal();
00472       }
00473     return NULL;
00474   }
00475   static void
00476   boxed_free (gpointer data)
00477   {
00478     if (data)
00479       {
00480         CSeq *cs = reinterpret_cast<CSeq*> (data);
00481         Sequence s;
00482         s.take (cs);
00483       }
00484   }
00485 };
00486 template<typename SeqType> SeqType
00487 cxx_value_get_boxed_sequence (const GValue *value)
00488 {
00489   if (SFI_VALUE_HOLDS_SEQ (value))
00490     {
00491       SfiSeq *seq = sfi_value_get_seq (value);
00492       return SeqType::from_seq (seq);
00493     }
00494   else
00495     {
00496       typename SeqType::CSeq *boxed = reinterpret_cast<typename SeqType::CSeq*> (g_value_get_boxed (value));
00497       if (boxed)
00498         {
00499           SeqType sh;
00500           sh.set_boxed (boxed);
00501           return sh;
00502         }
00503       else
00504         return SeqType();
00505     }
00506 }
00507 template<typename SeqType> void
00508 cxx_value_set_boxed_sequence (GValue        *value,
00509                               const SeqType &self)
00510 {
00511   if (SFI_VALUE_HOLDS_SEQ (value))
00512     {
00513       SfiSeq *seq = SeqType::to_seq (self);
00514       sfi_value_take_seq (value, seq);
00515     }
00516   else
00517     g_value_set_boxed (value, self.c_ptr());
00518 }
00519 
00520 class FBlock {
00521   SfiFBlock *block;
00522 public:
00523   typedef float*       iterator;
00524   typedef const float* const_iterator;
00525   FBlock (unsigned int length = 0)
00526   {
00527     block = sfi_fblock_new_sized (length);
00528   }
00529   FBlock (SfiFBlock &fblock)
00530   {
00531     block = NULL;
00532     *this = fblock;
00533   }
00534   FBlock (unsigned int length,
00535           const float *values)
00536   {
00537     block = sfi_fblock_new();
00538     sfi_fblock_append (block, length, values);
00539   }
00540   FBlock (const FBlock &fb)
00541   {
00542     if (fb.block)
00543       block = sfi_fblock_ref (fb.block);
00544     else
00545       block = sfi_fblock_new();
00546   }
00547   iterator
00548   begin()
00549   {
00550     return block ? block->values : NULL;
00551   }
00552   const_iterator
00553   begin() const
00554   {
00555     return block ? block->values : NULL;
00556   }
00557   iterator
00558   end()
00559   {
00560     return block ? block->values + block->n_values : NULL;
00561   }
00562   const_iterator
00563   end() const
00564   {
00565     return block ? block->values + block->n_values : NULL;
00566   }
00567   FBlock&
00568   operator= (SfiFBlock &fb)
00569   {
00570     if (block != &fb)
00571       {
00572         if (block)
00573           sfi_fblock_unref (block);
00574         block = &fb;
00575         if (block)
00576           sfi_fblock_ref (block);
00577       }
00578     return *this;
00579   }
00580   FBlock&
00581   operator= (const FBlock &s)
00582   {
00583     if (block != s.block)
00584       {
00585         if (block)
00586           sfi_fblock_unref (block);
00587         block = s.block;
00588         if (block)
00589           sfi_fblock_ref (block);
00590       }
00591     return *this;
00592   }
00593   SfiFBlock*
00594   fblock()
00595   {
00596     return block;
00597   }
00598   ~FBlock()
00599   {
00600     if (block)
00601       sfi_fblock_unref (block);
00602   }
00603   void
00604   ref ()
00605   {
00606     if (!block)
00607       block = sfi_fblock_new();
00608     sfi_fblock_ref (block);
00609   }
00610   void
00611   unref ()
00612   {
00613     g_return_if_fail (block != NULL && block->ref_count > 1);
00614     sfi_fblock_unref (block);
00615   }
00616   void
00617   resize (unsigned int length)
00618   {
00619     if (block)
00620       sfi_fblock_resize (block, length);
00621     else
00622       block = sfi_fblock_new_sized (length);
00623   }
00624   void
00625   take (SfiFBlock *fb)
00626   {
00627     if (block)
00628       sfi_fblock_unref (block);
00629     block = fb;
00630   }
00631   FBlock
00632   copy_deep()
00633   {
00634     if (block)
00635       return FBlock (block->n_values, block->values);
00636     else
00637       return FBlock (0);
00638   }
00639   FBlock
00640   copy_shallow()
00641   {
00642     return FBlock (*this);
00643   }
00644   void
00645   append (unsigned int length,
00646           const float *values)
00647   {
00648     if (!block)
00649       block = sfi_fblock_new();
00650     sfi_fblock_append (block, length, values);
00651   }
00652   void
00653   append (float f)
00654   {
00655     append (1, &f);
00656   }
00657   unsigned int
00658   length()
00659   {
00660     return block ? block->n_values : 0;
00661   }
00662   const float*
00663   get()
00664   {
00665     return block ? block->values : NULL;
00666   }
00667   static FBlock
00668   value_get_fblock (const GValue *value)
00669   {
00670     SfiFBlock *fb = sfi_value_get_fblock (value);
00671     FBlock self (0);
00672     if (fb)
00673       self.take (sfi_fblock_ref (fb));
00674     return self;
00675   }
00676   static void
00677   value_set_fblock (GValue       *value,
00678                     const FBlock &self)
00679   {
00680     sfi_value_set_fblock (value, self.block);
00681   }
00682 };
00683 
00684 class BBlock {
00685   SfiBBlock *block;
00686 public:
00687   BBlock (unsigned int length = 0)
00688   {
00689     block = sfi_bblock_new_sized (length);
00690   }
00691   BBlock (SfiBBlock &bblock)
00692   {
00693     block = NULL;
00694     *this = bblock;
00695   }
00696   BBlock (unsigned int  length,
00697           const guint8 *bytes)
00698   {
00699     block = sfi_bblock_new();
00700     sfi_bblock_append (block, length, bytes);
00701   }
00702   BBlock (const BBlock &bb)
00703   {
00704     if (bb.block)
00705       block = sfi_bblock_ref (bb.block);
00706     else
00707       block = sfi_bblock_new();
00708   }
00709   BBlock&
00710   operator= (SfiBBlock &bb)
00711   {
00712     if (block != &bb)
00713       {
00714         if (block)
00715           sfi_bblock_unref (block);
00716         block = &bb;
00717         if (block)
00718           sfi_bblock_ref (block);
00719       }
00720     return *this;
00721   }
00722   BBlock&
00723   operator= (const BBlock &s)
00724   {
00725     if (block != s.block)
00726       {
00727         if (block)
00728           sfi_bblock_unref (block);
00729         block = s.block;
00730         if (block)
00731           sfi_bblock_ref (block);
00732       }
00733     return *this;
00734   }
00735   SfiBBlock* bblock()
00736   {
00737     return block;
00738   }
00739   ~BBlock()
00740   {
00741     if (block)
00742       sfi_bblock_unref (block);
00743   }
00744   void
00745   ref ()
00746   {
00747     if (!block)
00748       block = sfi_bblock_new();
00749     sfi_bblock_ref (block);
00750   }
00751   void
00752   unref ()
00753   {
00754     g_return_if_fail (block != NULL && block->ref_count > 1);
00755     sfi_bblock_unref (block);
00756   }
00757   void resize (unsigned int length)
00758   {
00759     if (block)
00760       sfi_bblock_resize (block, length);
00761     else
00762       block = sfi_bblock_new_sized (length);
00763   }
00764   void
00765   take (SfiBBlock *bb)
00766   {
00767     if (block)
00768       sfi_bblock_unref (block);
00769     block = bb;
00770   }
00771   BBlock copy_deep()
00772   {
00773     if (block)
00774       return BBlock (block->n_bytes, block->bytes);
00775     else
00776       return BBlock (0);
00777   }
00778   BBlock copy_shallow()
00779   {
00780     return BBlock (*this);
00781   }
00782   void append (unsigned int  length,
00783                const guint8 *bytes)
00784   {
00785     if (!block)
00786       block = sfi_bblock_new();
00787     sfi_bblock_append (block, length, bytes);
00788   }
00789   void append (guint8 b)
00790   {
00791     append (1, &b);
00792   }
00793   unsigned int length()
00794   {
00795     return block ? block->n_bytes : 0;
00796   }
00797   const guint8* get()
00798   {
00799     return block ? block->bytes : NULL;
00800   }
00801   static BBlock value_get_bblock (const GValue *value)
00802   {
00803     SfiBBlock *bb = sfi_value_get_bblock (value);
00804     BBlock self (0);
00805     if (bb)
00806       self.take (sfi_bblock_ref (bb));
00807     return self;
00808   }
00809   static void value_set_bblock (GValue       *value,
00810                                 const BBlock &self)
00811   {
00812     sfi_value_set_bblock (value, self.block);
00813   }
00814 };
00815 
00816 class Rec {
00817   SfiRec *crec;
00818 public:
00819   Rec ()
00820   {
00821     crec = NULL;
00822   }
00823   Rec (SfiRec &sr)
00824   {
00825     crec = NULL;
00826     *this = sr;
00827   }
00828   Rec (const Rec &rr)
00829   {
00830     if (rr.crec)
00831       crec = sfi_rec_ref (rr.crec);
00832     else
00833       crec = NULL;
00834   }
00835   void clear ()
00836   {
00837     if (crec)
00838       sfi_rec_clear (crec);
00839   }
00840   Rec&
00841   operator= (SfiRec &sr)
00842   {
00843     if (crec != &sr)
00844       {
00845         if (crec)
00846           sfi_rec_unref (crec);
00847         crec = &sr;
00848         if (crec)
00849           sfi_rec_ref (crec);
00850       }
00851     return *this;
00852   }
00853   Rec&
00854   operator= (const Rec &rr)
00855   {
00856     if (crec != rr.crec)
00857       {
00858         if (crec)
00859           sfi_rec_unref (crec);
00860         crec = rr.crec;
00861         if (crec)
00862           sfi_rec_ref (crec);
00863       }
00864     return *this;
00865   }
00866   SfiRec* rec()
00867   {
00868     return crec;
00869   }
00870   ~Rec()
00871   {
00872     if (crec)
00873       sfi_rec_unref (crec);
00874   }
00875   void
00876   ref ()
00877   {
00878     if (!crec)
00879       crec = sfi_rec_new();
00880     sfi_rec_ref (crec);
00881   }
00882   void
00883   unref ()
00884   {
00885     g_return_if_fail (crec != NULL && crec->ref_count > 1);
00886     sfi_rec_unref (crec);
00887   }
00888   void
00889   take (SfiRec *sr)
00890   {
00891     if (crec)
00892       sfi_rec_unref (crec);
00893     crec = sr;
00894   }
00895   Rec copy_deep()
00896   {
00897     if (crec)
00898       return Rec (*sfi_rec_copy_deep (crec));
00899     else
00900       return Rec ();
00901   }
00902   Rec copy_shallow()
00903   {
00904     return Rec (*this);
00905   }
00906   void set (const gchar     *field_name,
00907             const GValue    *value)
00908   {
00909     if (!crec)
00910       crec = sfi_rec_new();
00911     sfi_rec_set (crec, field_name, value);
00912   }
00913   unsigned int length()
00914   {
00915     return crec ? crec->n_fields : 0;
00916   }
00917   GValue* get (const gchar *name)
00918   {
00919     return crec ? sfi_rec_get (crec, name) : NULL;
00920   }
00921   static Rec value_get_rec (const GValue *value)
00922   {
00923     SfiRec *sr = sfi_value_get_rec (value);
00924     Rec self;
00925     if (sr)
00926       self.take (sfi_rec_ref (sr));
00927     return self;
00928   }
00929   static void value_set_rec (GValue       *value,
00930                              const Rec &self)
00931   {
00932     sfi_value_set_rec (value, self.crec);
00933   }
00934 };
00935 
00936 class ObjectHandle {
00937   GObject *cobj;
00938 public:
00939   ObjectHandle ()
00940   {
00941     cobj = NULL;
00942   }
00943   ObjectHandle (GObject &object)
00944   {
00945     cobj = NULL;
00946     *this = object;
00947   }
00948   ObjectHandle (const ObjectHandle &oh)
00949   {
00950     if (oh.cobj)
00951       cobj = (GObject*) g_object_ref (oh.cobj);
00952     else
00953       cobj = NULL;
00954   }
00955   ~ObjectHandle()
00956   {
00957     if (cobj)
00958       g_object_unref (cobj);
00959   }
00960   ObjectHandle& operator= (GObject &object)
00961   {
00962     if (cobj != &object)
00963       {
00964         if (cobj)
00965           g_object_unref (cobj);
00966         cobj = &object;
00967         if (cobj)
00968           g_object_ref (cobj);
00969       }
00970     return *this;
00971   }
00972   ObjectHandle& operator= (const ObjectHandle &oh)
00973   {
00974     if (cobj != oh.cobj)
00975       {
00976         if (cobj)
00977           g_object_unref (cobj);
00978         cobj = oh.cobj;
00979         if (cobj)
00980           g_object_ref (cobj);
00981       }
00982     return *this;
00983   }
00984   GObject* object()
00985   {
00986     return cobj;
00987   }
00988   void
00989   ref ()
00990   {
00991     g_return_if_fail (cobj != NULL && cobj->ref_count > 0);
00992     g_object_ref (cobj);
00993   }
00994   void
00995   unref ()
00996   {
00997     g_return_if_fail (cobj != NULL && cobj->ref_count > 1);
00998     g_object_unref (cobj);
00999   }
01000   void
01001   take (GObject *object)
01002   {
01003     if (cobj)
01004       g_object_unref (cobj);
01005     cobj = object;
01006   }
01007   ObjectHandle copy_deep()
01008   {
01009     if (cobj)
01010       return ObjectHandle (*cobj);
01011     else
01012       return ObjectHandle ();
01013   }
01014   ObjectHandle copy_shallow()
01015   {
01016     return ObjectHandle (*this);
01017   }
01018   static ObjectHandle value_get (const GValue *value)
01019   {
01020     GObject *object = (GObject*) g_value_get_object (value);
01021     ObjectHandle self;
01022     if (object)
01023       self.take ((GObject*) g_object_ref (object));
01024     return self;
01025   }
01026   static void value_set (GValue             *value,
01027                          const ObjectHandle &self)
01028   {
01029     g_value_set_object (value, self.cobj);
01030   }
01031 };
01032 
01033 template<typename Type> void
01034 cxx_boxed_to_rec (const GValue *src_value,
01035                   GValue       *dest_value)
01036 {
01037   SfiRec *rec = NULL;
01038   gpointer boxed = g_value_get_boxed (src_value);
01039   if (boxed)
01040     {
01041       Type *t = reinterpret_cast<Type*> (boxed);
01042       rec = Type::to_rec (*t);
01043     }
01044   sfi_value_take_rec (dest_value, rec);
01045 }
01046 
01047 template<typename Type> void
01048 cxx_boxed_from_rec (const GValue *src_value,
01049                     GValue       *dest_value)
01050 {
01051   gpointer boxed = NULL;
01052   SfiRec *rec = sfi_value_get_rec (src_value);
01053   if (rec)
01054     {
01055       RecordHandle<Type> rh = Type::from_rec (rec);
01056       Type *t = rh.steal();
01057       boxed = t;
01058     }
01059   g_value_take_boxed (dest_value, boxed);
01060 }
01061 
01062 template<typename SeqType> void
01063 cxx_boxed_to_seq (const GValue *src_value,
01064                   GValue       *dest_value)
01065 {
01066   SfiSeq *seq = NULL;
01067   gpointer boxed = g_value_get_boxed (src_value);
01068   if (boxed)
01069     {
01070       typename SeqType::CSeq *t = reinterpret_cast<typename SeqType::CSeq*> (boxed);
01071       SeqType cxxseq;
01072       cxxseq.take(t);   /* temporarily re-own */
01073       seq = SeqType::to_seq (cxxseq);
01074       cxxseq.steal();   /* get back */
01075     }
01076   sfi_value_take_seq (dest_value, seq);
01077 }
01078 
01079 template<typename SeqType> void
01080 cxx_boxed_from_seq (const GValue *src_value,
01081                     GValue       *dest_value)
01082 {
01083   gpointer boxed = NULL;
01084   SfiSeq *seq = sfi_value_get_seq (src_value);
01085   if (seq)
01086     {
01087       SeqType sh = SeqType::from_seq (seq);
01088       typename SeqType::CSeq *t = sh.steal();
01089       boxed = t;
01090     }
01091   g_value_take_boxed (dest_value, boxed);
01092 }
01093 
01094 template<typename Type> RecordHandle<Type>
01095 cxx_value_get_rec (const GValue *value)
01096 {
01097   SfiRec *rec = sfi_value_get_rec (value);
01098   if (rec)
01099     return Type::from_rec (rec);
01100   else
01101     return INIT_NULL;
01102 }
01103 
01104 template<typename Type> void
01105 cxx_value_set_rec (GValue                   *value,
01106                    const RecordHandle<Type> &self)
01107 {
01108   if (self)
01109     sfi_value_take_rec (value, Type::to_rec (self));
01110   else
01111     sfi_value_set_rec (value, NULL);
01112 }
01113 
01114 template<typename SeqType> SeqType
01115 cxx_value_get_seq (const GValue *value)
01116 {
01117   SfiSeq *seq = sfi_value_get_seq (value);
01118   if (seq)
01119     return SeqType::from_seq (seq);
01120   else
01121     return SeqType();
01122 }
01123 
01124 template<typename SeqType> void
01125 cxx_value_set_seq (GValue        *value,
01126                    const SeqType &self)
01127 {
01128   sfi_value_take_seq (value, SeqType::to_seq (self));
01129 }
01130 
01131 // == C++ Auxillaries ==
01132 struct Init { // stolen from Rapicorn
01133   explicit Init (void (*f) ()) { f(); }
01134 };
01135 
01136 } // Sfi
01137 
01138 #endif /* __SFI_CXX_H__ */
01139 
01140 /* vim:set ts=8 sts=2 sw=2: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines