BEAST/BSE - Better Audio System and Sound Engine
0.8.2
|
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: */