1 ///////////////////////////////////////////////////////////////////////////// 2 // Name: wx/variant.h 3 // Purpose: wxVariant class, container for any type 4 // Author: Julian Smart 5 // Modified by: 6 // Created: 10/09/98 7 // Copyright: (c) Julian Smart 8 // Licence: wxWindows licence 9 ///////////////////////////////////////////////////////////////////////////// 10 11 #ifndef _WX_VARIANT_H_ 12 #define _WX_VARIANT_H_ 13 14 #include "wx/defs.h" 15 16 #if wxUSE_VARIANT 17 18 #include "wx/object.h" 19 #include "wx/string.h" 20 #include "wx/arrstr.h" 21 #include "wx/list.h" 22 #include "wx/cpp.h" 23 #include "wx/longlong.h" 24 25 #if wxUSE_DATETIME 26 #include "wx/datetime.h" 27 #endif // wxUSE_DATETIME 28 29 #include "wx/iosfwrap.h" 30 31 class wxAny; 32 33 /* 34 * wxVariantData stores the actual data in a wxVariant object, 35 * to allow it to store any type of data. 36 * Derive from this to provide custom data handling. 37 * 38 * NB: When you construct a wxVariantData, it will have refcount 39 * of one. Refcount will not be further increased when 40 * it is passed to wxVariant. This simulates old common 41 * scenario where wxVariant took ownership of wxVariantData 42 * passed to it. 43 * If you create wxVariantData for other reasons than passing 44 * it to wxVariant, technically you are not required to call 45 * DecRef() before deleting it. 46 * 47 * TODO: in order to replace wxPropertyValue, we would need 48 * to consider adding constructors that take pointers to C++ variables, 49 * or removing that functionality from the wxProperty library. 50 * Essentially wxPropertyValue takes on some of the wxValidator functionality 51 * by storing pointers and not just actual values, allowing update of C++ data 52 * to be handled automatically. Perhaps there's another way of doing this without 53 * overloading wxVariant with unnecessary functionality. 54 */ 55 56 class WXDLLIMPEXP_BASE wxVariantData : public wxObjectRefData 57 { 58 friend class wxVariant; 59 public: wxVariantData()60 wxVariantData() { } 61 62 // Override these to provide common functionality 63 virtual bool Eq(wxVariantData& data) const = 0; 64 65 #if wxUSE_STD_IOSTREAM Write(wxSTD ostream & WXUNUSED (str))66 virtual bool Write(wxSTD ostream& WXUNUSED(str)) const { return false; } 67 #endif Write(wxString & WXUNUSED (str))68 virtual bool Write(wxString& WXUNUSED(str)) const { return false; } 69 #if wxUSE_STD_IOSTREAM Read(wxSTD istream & WXUNUSED (str))70 virtual bool Read(wxSTD istream& WXUNUSED(str)) { return false; } 71 #endif Read(wxString & WXUNUSED (str))72 virtual bool Read(wxString& WXUNUSED(str)) { return false; } 73 // What type is it? Return a string name. 74 virtual wxString GetType() const = 0; 75 // If it based on wxObject return the ClassInfo. GetValueClassInfo()76 virtual wxClassInfo* GetValueClassInfo() { return NULL; } 77 78 // Implement this to make wxVariant::UnShare work. Returns 79 // a copy of the data. Clone()80 virtual wxVariantData* Clone() const { return NULL; } 81 82 #if wxUSE_ANY 83 // Converts value to wxAny, if possible. Return true if successful. GetAsAny(wxAny * WXUNUSED (any))84 virtual bool GetAsAny(wxAny* WXUNUSED(any)) const { return false; } 85 #endif 86 87 protected: 88 // Protected dtor should make some incompatible code 89 // break more louder. That is, they should do data->DecRef() 90 // instead of delete data. ~wxVariantData()91 virtual ~wxVariantData() { } 92 }; 93 94 /* 95 * wxVariant can store any kind of data, but has some basic types 96 * built in. 97 */ 98 99 class WXDLLIMPEXP_FWD_BASE wxVariant; 100 101 WX_DECLARE_LIST_WITH_DECL(wxVariant, wxVariantList, class WXDLLIMPEXP_BASE); 102 103 class WXDLLIMPEXP_BASE wxVariant: public wxObject 104 { 105 public: 106 wxVariant(); 107 108 wxVariant(const wxVariant& variant); 109 wxVariant(wxVariantData* data, const wxString& name = wxEmptyString); 110 #if wxUSE_ANY 111 wxVariant(const wxAny& any); 112 #endif 113 virtual ~wxVariant(); 114 115 // generic assignment 116 void operator= (const wxVariant& variant); 117 118 // Assignment using data, e.g. 119 // myVariant = new wxStringVariantData("hello"); 120 void operator= (wxVariantData* variantData); 121 122 bool operator== (const wxVariant& variant) const; 123 bool operator!= (const wxVariant& variant) const; 124 125 // Sets/gets name SetName(const wxString & name)126 inline void SetName(const wxString& name) { m_name = name; } GetName()127 inline const wxString& GetName() const { return m_name; } 128 129 // Tests whether there is data 130 bool IsNull() const; 131 132 // For compatibility with wxWidgets <= 2.6, this doesn't increase 133 // reference count. GetData()134 wxVariantData* GetData() const 135 { 136 return (wxVariantData*) m_refData; 137 } 138 void SetData(wxVariantData* data) ; 139 140 // make a 'clone' of the object Ref(const wxVariant & clone)141 void Ref(const wxVariant& clone) { wxObject::Ref(clone); } 142 143 // ensure that the data is exclusive to this variant, and not shared 144 bool Unshare(); 145 146 // Make NULL (i.e. delete the data) 147 void MakeNull(); 148 149 // Delete data and name 150 void Clear(); 151 152 // Returns a string representing the type of the variant, 153 // e.g. "string", "bool", "stringlist", "list", "double", "long" 154 wxString GetType() const; 155 156 bool IsType(const wxString& type) const; 157 bool IsValueKindOf(const wxClassInfo* type) const; 158 159 // write contents to a string (e.g. for debugging) 160 wxString MakeString() const; 161 162 #if wxUSE_ANY 163 wxAny GetAny() const; 164 #endif 165 166 // double 167 wxVariant(double val, const wxString& name = wxEmptyString); 168 bool operator== (double value) const; 169 bool operator!= (double value) const; 170 void operator= (double value) ; 171 inline operator double () const { return GetDouble(); } GetReal()172 inline double GetReal() const { return GetDouble(); } 173 double GetDouble() const; 174 175 // long 176 wxVariant(long val, const wxString& name = wxEmptyString); 177 wxVariant(int val, const wxString& name = wxEmptyString); 178 wxVariant(short val, const wxString& name = wxEmptyString); 179 bool operator== (long value) const; 180 bool operator!= (long value) const; 181 void operator= (long value) ; 182 inline operator long () const { return GetLong(); } GetInteger()183 inline long GetInteger() const { return GetLong(); } 184 long GetLong() const; 185 186 // bool 187 wxVariant(bool val, const wxString& name = wxEmptyString); 188 bool operator== (bool value) const; 189 bool operator!= (bool value) const; 190 void operator= (bool value) ; 191 inline operator bool () const { return GetBool(); } 192 bool GetBool() const ; 193 194 // wxDateTime 195 #if wxUSE_DATETIME 196 wxVariant(const wxDateTime& val, const wxString& name = wxEmptyString); 197 bool operator== (const wxDateTime& value) const; 198 bool operator!= (const wxDateTime& value) const; 199 void operator= (const wxDateTime& value) ; wxDateTime()200 inline operator wxDateTime () const { return GetDateTime(); } 201 wxDateTime GetDateTime() const; 202 #endif 203 204 // wxString 205 wxVariant(const wxString& val, const wxString& name = wxEmptyString); 206 // these overloads are necessary to prevent the compiler from using bool 207 // version instead of wxString one: 208 wxVariant(const char* val, const wxString& name = wxEmptyString); 209 wxVariant(const wchar_t* val, const wxString& name = wxEmptyString); 210 wxVariant(const wxCStrData& val, const wxString& name = wxEmptyString); 211 wxVariant(const wxScopedCharBuffer& val, const wxString& name = wxEmptyString); 212 wxVariant(const wxScopedWCharBuffer& val, const wxString& name = wxEmptyString); 213 214 bool operator== (const wxString& value) const; 215 bool operator!= (const wxString& value) const; 216 wxVariant& operator=(const wxString& value); 217 // these overloads are necessary to prevent the compiler from using bool 218 // version instead of wxString one: 219 wxVariant& operator=(const char* value) 220 { return *this = wxString(value); } 221 wxVariant& operator=(const wchar_t* value) 222 { return *this = wxString(value); } 223 wxVariant& operator=(const wxCStrData& value) 224 { return *this = value.AsString(); } 225 template<typename T> 226 wxVariant& operator=(const wxScopedCharTypeBuffer<T>& value) 227 { return *this = value.data(); } 228 wxString()229 inline operator wxString () const { return MakeString(); } 230 wxString GetString() const; 231 232 #if wxUSE_STD_STRING 233 wxVariant(const std::string& val, const wxString& name = wxEmptyString); 234 bool operator==(const std::string& value) const 235 { return operator==(wxString(value)); } 236 bool operator!=(const std::string& value) const 237 { return operator!=(wxString(value)); } 238 wxVariant& operator=(const std::string& value) 239 { return operator=(wxString(value)); } string()240 operator std::string() const { return (operator wxString()).ToStdString(); } 241 242 wxVariant(const wxStdWideString& val, const wxString& name = wxEmptyString); 243 bool operator==(const wxStdWideString& value) const 244 { return operator==(wxString(value)); } 245 bool operator!=(const wxStdWideString& value) const 246 { return operator!=(wxString(value)); } 247 wxVariant& operator=(const wxStdWideString& value) 248 { return operator=(wxString(value)); } wxStdWideString()249 operator wxStdWideString() const { return (operator wxString()).ToStdWstring(); } 250 #endif // wxUSE_STD_STRING 251 252 // wxUniChar 253 wxVariant(const wxUniChar& val, const wxString& name = wxEmptyString); 254 wxVariant(const wxUniCharRef& val, const wxString& name = wxEmptyString); 255 wxVariant(char val, const wxString& name = wxEmptyString); 256 wxVariant(wchar_t val, const wxString& name = wxEmptyString); 257 bool operator==(const wxUniChar& value) const; 258 bool operator==(const wxUniCharRef& value) const { return *this == wxUniChar(value); } 259 bool operator==(char value) const { return *this == wxUniChar(value); } 260 bool operator==(wchar_t value) const { return *this == wxUniChar(value); } 261 bool operator!=(const wxUniChar& value) const { return !(*this == value); } 262 bool operator!=(const wxUniCharRef& value) const { return !(*this == value); } 263 bool operator!=(char value) const { return !(*this == value); } 264 bool operator!=(wchar_t value) const { return !(*this == value); } 265 wxVariant& operator=(const wxUniChar& value); 266 wxVariant& operator=(const wxUniCharRef& value) { return *this = wxUniChar(value); } 267 wxVariant& operator=(char value) { return *this = wxUniChar(value); } 268 wxVariant& operator=(wchar_t value) { return *this = wxUniChar(value); } wxUniChar()269 operator wxUniChar() const { return GetChar(); } 270 operator char() const { return GetChar(); } wchar_t()271 operator wchar_t() const { return GetChar(); } 272 wxUniChar GetChar() const; 273 274 // wxArrayString 275 wxVariant(const wxArrayString& val, const wxString& name = wxEmptyString); 276 bool operator== (const wxArrayString& value) const; 277 bool operator!= (const wxArrayString& value) const; 278 void operator= (const wxArrayString& value); wxArrayString()279 operator wxArrayString () const { return GetArrayString(); } 280 wxArrayString GetArrayString() const; 281 282 // void* 283 wxVariant(void* ptr, const wxString& name = wxEmptyString); 284 bool operator== (void* value) const; 285 bool operator!= (void* value) const; 286 void operator= (void* value); 287 operator void* () const { return GetVoidPtr(); } 288 void* GetVoidPtr() const; 289 290 // wxObject* 291 wxVariant(wxObject* ptr, const wxString& name = wxEmptyString); 292 bool operator== (wxObject* value) const; 293 bool operator!= (wxObject* value) const; 294 void operator= (wxObject* value); 295 wxObject* GetWxObjectPtr() const; 296 297 #if wxUSE_LONGLONG 298 // wxLongLong 299 wxVariant(wxLongLong, const wxString& name = wxEmptyString); 300 bool operator==(wxLongLong value) const; 301 bool operator!=(wxLongLong value) const; 302 void operator=(wxLongLong value); wxLongLong()303 operator wxLongLong() const { return GetLongLong(); } 304 wxLongLong GetLongLong() const; 305 306 // wxULongLong 307 wxVariant(wxULongLong, const wxString& name = wxEmptyString); 308 bool operator==(wxULongLong value) const; 309 bool operator!=(wxULongLong value) const; 310 void operator=(wxULongLong value); wxULongLong()311 operator wxULongLong() const { return GetULongLong(); } 312 wxULongLong GetULongLong() const; 313 #endif 314 315 // ------------------------------ 316 // list operations 317 // ------------------------------ 318 319 wxVariant(const wxVariantList& val, const wxString& name = wxEmptyString); // List of variants 320 bool operator== (const wxVariantList& value) const; 321 bool operator!= (const wxVariantList& value) const; 322 void operator= (const wxVariantList& value) ; 323 // Treat a list variant as an array 324 wxVariant operator[] (size_t idx) const; 325 wxVariant& operator[] (size_t idx) ; 326 wxVariantList& GetList() const ; 327 328 // Return the number of elements in a list 329 size_t GetCount() const; 330 331 // Make empty list 332 void NullList(); 333 334 // Append to list 335 void Append(const wxVariant& value); 336 337 // Insert at front of list 338 void Insert(const wxVariant& value); 339 340 // Returns true if the variant is a member of the list 341 bool Member(const wxVariant& value) const; 342 343 // Deletes the nth element of the list 344 bool Delete(size_t item); 345 346 // Clear list 347 void ClearList(); 348 349 public: 350 // Type conversion 351 bool Convert(long* value) const; 352 bool Convert(bool* value) const; 353 bool Convert(double* value) const; 354 bool Convert(wxString* value) const; 355 bool Convert(wxUniChar* value) const; 356 bool Convert(char* value) const; 357 bool Convert(wchar_t* value) const; 358 #if wxUSE_DATETIME 359 bool Convert(wxDateTime* value) const; 360 #endif // wxUSE_DATETIME 361 #if wxUSE_LONGLONG 362 bool Convert(wxLongLong* value) const; 363 bool Convert(wxULongLong* value) const; 364 #ifdef wxLongLong_t Convert(wxLongLong_t * value)365 bool Convert(wxLongLong_t* value) const 366 { 367 wxLongLong temp; 368 if ( !Convert(&temp) ) 369 return false; 370 *value = temp.GetValue(); 371 return true; 372 } Convert(wxULongLong_t * value)373 bool Convert(wxULongLong_t* value) const 374 { 375 wxULongLong temp; 376 if ( !Convert(&temp) ) 377 return false; 378 *value = temp.GetValue(); 379 return true; 380 } 381 #endif // wxLongLong_t 382 #endif // wxUSE_LONGLONG 383 384 // Attributes 385 protected: 386 virtual wxObjectRefData *CreateRefData() const; 387 virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; 388 389 wxString m_name; 390 391 private: 392 DECLARE_DYNAMIC_CLASS(wxVariant) 393 }; 394 395 396 // 397 // wxVariant <-> wxAny conversion code 398 // 399 #if wxUSE_ANY 400 401 #include "wx/any.h" 402 403 // In order to convert wxAny to wxVariant, we need to be able to associate 404 // wxAnyValueType with a wxVariantData factory function. 405 typedef wxVariantData* (*wxVariantDataFactory)(const wxAny& any); 406 407 // Actual Any-to-Variant registration must be postponed to a time when all 408 // global variables have been initialized. Hence this arrangement. 409 // wxAnyToVariantRegistration instances are kept in global scope and 410 // wxAnyValueTypeGlobals in any.cpp will use their data when the time is 411 // right. 412 class WXDLLIMPEXP_BASE wxAnyToVariantRegistration 413 { 414 public: 415 wxAnyToVariantRegistration(wxVariantDataFactory factory); 416 virtual ~wxAnyToVariantRegistration(); 417 418 virtual wxAnyValueType* GetAssociatedType() = 0; GetFactory()419 wxVariantDataFactory GetFactory() const { return m_factory; } 420 private: 421 wxVariantDataFactory m_factory; 422 }; 423 424 template<typename T> 425 class wxAnyToVariantRegistrationImpl : public wxAnyToVariantRegistration 426 { 427 public: wxAnyToVariantRegistrationImpl(wxVariantDataFactory factory)428 wxAnyToVariantRegistrationImpl(wxVariantDataFactory factory) 429 : wxAnyToVariantRegistration(factory) 430 { 431 } 432 GetAssociatedType()433 virtual wxAnyValueType* GetAssociatedType() 434 { 435 return wxAnyValueTypeImpl<T>::GetInstance(); 436 } 437 private: 438 }; 439 440 #define DECLARE_WXANY_CONVERSION() \ 441 virtual bool GetAsAny(wxAny* any) const; \ 442 static wxVariantData* VariantDataFactory(const wxAny& any); 443 444 #define _REGISTER_WXANY_CONVERSION(T, CLASSNAME, FUNC) \ 445 static wxAnyToVariantRegistrationImpl<T> \ 446 gs_##CLASSNAME##AnyToVariantRegistration = \ 447 wxAnyToVariantRegistrationImpl<T>(&FUNC); 448 449 #define REGISTER_WXANY_CONVERSION(T, CLASSNAME) \ 450 _REGISTER_WXANY_CONVERSION(T, CLASSNAME, CLASSNAME::VariantDataFactory) 451 452 #define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME) \ 453 bool CLASSNAME::GetAsAny(wxAny* any) const \ 454 { \ 455 *any = m_value; \ 456 return true; \ 457 } \ 458 wxVariantData* CLASSNAME::VariantDataFactory(const wxAny& any) \ 459 { \ 460 return new CLASSNAME(wxANY_AS(any, T)); \ 461 } \ 462 REGISTER_WXANY_CONVERSION(T, CLASSNAME) 463 464 #else // if !wxUSE_ANY 465 466 #define DECLARE_WXANY_CONVERSION() 467 #define REGISTER_WXANY_CONVERSION(T, CLASSNAME) 468 #define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME) 469 470 #endif // wxUSE_ANY/!wxUSE_ANY 471 472 473 #define DECLARE_VARIANT_OBJECT(classname) \ 474 DECLARE_VARIANT_OBJECT_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE) 475 476 #define DECLARE_VARIANT_OBJECT_EXPORTED(classname,expdecl) \ 477 expdecl classname& operator << ( classname &object, const wxVariant &variant ); \ 478 expdecl wxVariant& operator << ( wxVariant &variant, const classname &object ); 479 480 #define IMPLEMENT_VARIANT_OBJECT(classname) \ 481 IMPLEMENT_VARIANT_OBJECT_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE) 482 483 #define IMPLEMENT_VARIANT_OBJECT_EXPORTED_NO_EQ(classname,expdecl) \ 484 class classname##VariantData: public wxVariantData \ 485 { \ 486 public:\ 487 classname##VariantData() {} \ 488 classname##VariantData( const classname &value ) { m_value = value; } \ 489 \ 490 classname &GetValue() { return m_value; } \ 491 \ 492 virtual bool Eq(wxVariantData& data) const; \ 493 \ 494 virtual wxString GetType() const; \ 495 virtual wxClassInfo* GetValueClassInfo(); \ 496 \ 497 virtual wxVariantData* Clone() const { return new classname##VariantData(m_value); } \ 498 \ 499 DECLARE_WXANY_CONVERSION() \ 500 protected:\ 501 classname m_value; \ 502 };\ 503 \ 504 wxString classname##VariantData::GetType() const\ 505 {\ 506 return m_value.GetClassInfo()->GetClassName();\ 507 }\ 508 \ 509 wxClassInfo* classname##VariantData::GetValueClassInfo()\ 510 {\ 511 return m_value.GetClassInfo();\ 512 }\ 513 \ 514 expdecl classname& operator << ( classname &value, const wxVariant &variant )\ 515 {\ 516 wxASSERT( variant.GetType() == #classname );\ 517 \ 518 classname##VariantData *data = (classname##VariantData*) variant.GetData();\ 519 value = data->GetValue();\ 520 return value;\ 521 }\ 522 \ 523 expdecl wxVariant& operator << ( wxVariant &variant, const classname &value )\ 524 {\ 525 classname##VariantData *data = new classname##VariantData( value );\ 526 variant.SetData( data );\ 527 return variant;\ 528 } \ 529 IMPLEMENT_TRIVIAL_WXANY_CONVERSION(classname, classname##VariantData) 530 531 // implements a wxVariantData-derived class using for the Eq() method the 532 // operator== which must have been provided by "classname" 533 #define IMPLEMENT_VARIANT_OBJECT_EXPORTED(classname,expdecl) \ 534 IMPLEMENT_VARIANT_OBJECT_EXPORTED_NO_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl) \ 535 \ 536 bool classname##VariantData::Eq(wxVariantData& data) const \ 537 {\ 538 wxASSERT( GetType() == data.GetType() );\ 539 \ 540 classname##VariantData & otherData = (classname##VariantData &) data;\ 541 \ 542 return otherData.m_value == m_value;\ 543 }\ 544 545 546 // implements a wxVariantData-derived class using for the Eq() method a shallow 547 // comparison (through wxObject::IsSameAs function) 548 #define IMPLEMENT_VARIANT_OBJECT_SHALLOWCMP(classname) \ 549 IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(classname, wxEMPTY_PARAMETER_VALUE) 550 #define IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(classname,expdecl) \ 551 IMPLEMENT_VARIANT_OBJECT_EXPORTED_NO_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl) \ 552 \ 553 bool classname##VariantData::Eq(wxVariantData& data) const \ 554 {\ 555 wxASSERT( GetType() == data.GetType() );\ 556 \ 557 classname##VariantData & otherData = (classname##VariantData &) data;\ 558 \ 559 return (otherData.m_value.IsSameAs(m_value));\ 560 }\ 561 562 563 // Since we want type safety wxVariant we need to fetch and dynamic_cast 564 // in a seemingly safe way so the compiler can check, so we define 565 // a dynamic_cast /wxDynamicCast analogue. 566 567 #define wxGetVariantCast(var,classname) \ 568 ((classname*)(var.IsValueKindOf(&classname::ms_classInfo) ?\ 569 var.GetWxObjectPtr() : NULL)); 570 571 // Replacement for using wxDynamicCast on a wxVariantData object 572 #ifndef wxNO_RTTI 573 #define wxDynamicCastVariantData(data, classname) dynamic_cast<classname*>(data) 574 #endif 575 576 #define wxStaticCastVariantData(data, classname) static_cast<classname*>(data) 577 578 extern wxVariant WXDLLIMPEXP_BASE wxNullVariant; 579 580 #endif // wxUSE_VARIANT 581 582 #endif // _WX_VARIANT_H_ 583