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 #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING 220 wxVariant& operator=(const char* value) 221 { return *this = wxString(value); } 222 #endif // wxNO_IMPLICIT_WXSTRING_ENCODING 223 wxVariant& operator=(const wchar_t* value) 224 { return *this = wxString(value); } 225 wxVariant& operator=(const wxCStrData& value) 226 { return *this = value.AsString(); } 227 template<typename T> 228 wxVariant& operator=(const wxScopedCharTypeBuffer<T>& value) 229 { return *this = value.data(); } 230 wxString()231 inline operator wxString () const { return MakeString(); } 232 wxString GetString() const; 233 234 #if wxUSE_STD_STRING 235 #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING 236 wxVariant(const std::string& val, const wxString& name = wxEmptyString); 237 bool operator==(const std::string& value) const 238 { return operator==(wxString(value)); } 239 bool operator!=(const std::string& value) const 240 { return operator!=(wxString(value)); } 241 wxVariant& operator=(const std::string& value) 242 { return operator=(wxString(value)); } string()243 operator std::string() const { return (operator wxString()).ToStdString(); } 244 #endif // wxNO_IMPLICIT_WXSTRING_ENCODING 245 246 wxVariant(const wxStdWideString& val, const wxString& name = wxEmptyString); 247 bool operator==(const wxStdWideString& value) const 248 { return operator==(wxString(value)); } 249 bool operator!=(const wxStdWideString& value) const 250 { return operator!=(wxString(value)); } 251 wxVariant& operator=(const wxStdWideString& value) 252 { return operator=(wxString(value)); } wxStdWideString()253 operator wxStdWideString() const { return (operator wxString()).ToStdWstring(); } 254 #endif // wxUSE_STD_STRING 255 256 // wxUniChar 257 wxVariant(const wxUniChar& val, const wxString& name = wxEmptyString); 258 wxVariant(const wxUniCharRef& val, const wxString& name = wxEmptyString); 259 wxVariant(char val, const wxString& name = wxEmptyString); 260 wxVariant(wchar_t val, const wxString& name = wxEmptyString); 261 bool operator==(const wxUniChar& value) const; 262 bool operator==(const wxUniCharRef& value) const { return *this == wxUniChar(value); } 263 bool operator==(char value) const { return *this == wxUniChar(value); } 264 bool operator==(wchar_t value) const { return *this == wxUniChar(value); } 265 bool operator!=(const wxUniChar& value) const { return !(*this == value); } 266 bool operator!=(const wxUniCharRef& value) const { return !(*this == value); } 267 bool operator!=(char value) const { return !(*this == value); } 268 bool operator!=(wchar_t value) const { return !(*this == value); } 269 wxVariant& operator=(const wxUniChar& value); 270 wxVariant& operator=(const wxUniCharRef& value) { return *this = wxUniChar(value); } 271 wxVariant& operator=(char value) { return *this = wxUniChar(value); } 272 wxVariant& operator=(wchar_t value) { return *this = wxUniChar(value); } wxUniChar()273 operator wxUniChar() const { return GetChar(); } 274 operator char() const { return GetChar(); } wchar_t()275 operator wchar_t() const { return GetChar(); } 276 wxUniChar GetChar() const; 277 278 // wxArrayString 279 wxVariant(const wxArrayString& val, const wxString& name = wxEmptyString); 280 bool operator== (const wxArrayString& value) const; 281 bool operator!= (const wxArrayString& value) const; 282 void operator= (const wxArrayString& value); wxArrayString()283 operator wxArrayString () const { return GetArrayString(); } 284 wxArrayString GetArrayString() const; 285 286 // void* 287 wxVariant(void* ptr, const wxString& name = wxEmptyString); 288 bool operator== (void* value) const; 289 bool operator!= (void* value) const; 290 void operator= (void* value); 291 operator void* () const { return GetVoidPtr(); } 292 void* GetVoidPtr() const; 293 294 // wxObject* 295 wxVariant(wxObject* ptr, const wxString& name = wxEmptyString); 296 bool operator== (wxObject* value) const; 297 bool operator!= (wxObject* value) const; 298 void operator= (wxObject* value); 299 wxObject* GetWxObjectPtr() const; 300 301 #if wxUSE_LONGLONG 302 // wxLongLong 303 wxVariant(wxLongLong, const wxString& name = wxEmptyString); 304 bool operator==(wxLongLong value) const; 305 bool operator!=(wxLongLong value) const; 306 void operator=(wxLongLong value); wxLongLong()307 operator wxLongLong() const { return GetLongLong(); } 308 wxLongLong GetLongLong() const; 309 310 // wxULongLong 311 wxVariant(wxULongLong, const wxString& name = wxEmptyString); 312 bool operator==(wxULongLong value) const; 313 bool operator!=(wxULongLong value) const; 314 void operator=(wxULongLong value); wxULongLong()315 operator wxULongLong() const { return GetULongLong(); } 316 wxULongLong GetULongLong() const; 317 #endif 318 319 // ------------------------------ 320 // list operations 321 // ------------------------------ 322 323 wxVariant(const wxVariantList& val, const wxString& name = wxEmptyString); // List of variants 324 bool operator== (const wxVariantList& value) const; 325 bool operator!= (const wxVariantList& value) const; 326 void operator= (const wxVariantList& value) ; 327 // Treat a list variant as an array 328 wxVariant operator[] (size_t idx) const; 329 wxVariant& operator[] (size_t idx) ; 330 wxVariantList& GetList() const ; 331 332 // Return the number of elements in a list 333 size_t GetCount() const; 334 335 // Make empty list 336 void NullList(); 337 338 // Append to list 339 void Append(const wxVariant& value); 340 341 // Insert at front of list 342 void Insert(const wxVariant& value); 343 344 // Returns true if the variant is a member of the list 345 bool Member(const wxVariant& value) const; 346 347 // Deletes the nth element of the list 348 bool Delete(size_t item); 349 350 // Clear list 351 void ClearList(); 352 353 public: 354 // Type conversion 355 bool Convert(long* value) const; 356 bool Convert(bool* value) const; 357 bool Convert(double* value) const; 358 bool Convert(wxString* value) const; 359 bool Convert(wxUniChar* value) const; 360 bool Convert(char* value) const; 361 bool Convert(wchar_t* value) const; 362 #if wxUSE_DATETIME 363 bool Convert(wxDateTime* value) const; 364 #endif // wxUSE_DATETIME 365 #if wxUSE_LONGLONG 366 bool Convert(wxLongLong* value) const; 367 bool Convert(wxULongLong* value) const; 368 #ifdef wxLongLong_t Convert(wxLongLong_t * value)369 bool Convert(wxLongLong_t* value) const 370 { 371 wxLongLong temp; 372 if ( !Convert(&temp) ) 373 return false; 374 *value = temp.GetValue(); 375 return true; 376 } Convert(wxULongLong_t * value)377 bool Convert(wxULongLong_t* value) const 378 { 379 wxULongLong temp; 380 if ( !Convert(&temp) ) 381 return false; 382 *value = temp.GetValue(); 383 return true; 384 } 385 #endif // wxLongLong_t 386 #endif // wxUSE_LONGLONG 387 388 // Attributes 389 protected: 390 virtual wxObjectRefData *CreateRefData() const wxOVERRIDE; 391 virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const wxOVERRIDE; 392 393 wxString m_name; 394 395 private: 396 wxDECLARE_DYNAMIC_CLASS(wxVariant); 397 }; 398 399 400 // 401 // wxVariant <-> wxAny conversion code 402 // 403 #if wxUSE_ANY 404 405 #include "wx/any.h" 406 407 // In order to convert wxAny to wxVariant, we need to be able to associate 408 // wxAnyValueType with a wxVariantData factory function. 409 typedef wxVariantData* (*wxVariantDataFactory)(const wxAny& any); 410 411 // Actual Any-to-Variant registration must be postponed to a time when all 412 // global variables have been initialized. Hence this arrangement. 413 // wxAnyToVariantRegistration instances are kept in global scope and 414 // wxAnyValueTypeGlobals in any.cpp will use their data when the time is 415 // right. 416 class WXDLLIMPEXP_BASE wxAnyToVariantRegistration 417 { 418 public: 419 wxAnyToVariantRegistration(wxVariantDataFactory factory); 420 virtual ~wxAnyToVariantRegistration(); 421 422 virtual wxAnyValueType* GetAssociatedType() = 0; GetFactory()423 wxVariantDataFactory GetFactory() const { return m_factory; } 424 private: 425 wxVariantDataFactory m_factory; 426 }; 427 428 template<typename T> 429 class wxAnyToVariantRegistrationImpl : public wxAnyToVariantRegistration 430 { 431 public: wxAnyToVariantRegistrationImpl(wxVariantDataFactory factory)432 wxAnyToVariantRegistrationImpl(wxVariantDataFactory factory) 433 : wxAnyToVariantRegistration(factory) 434 { 435 } 436 GetAssociatedType()437 virtual wxAnyValueType* GetAssociatedType() wxOVERRIDE 438 { 439 return wxAnyValueTypeImpl<T>::GetInstance(); 440 } 441 private: 442 }; 443 444 #define DECLARE_WXANY_CONVERSION() \ 445 virtual bool GetAsAny(wxAny* any) const wxOVERRIDE; \ 446 static wxVariantData* VariantDataFactory(const wxAny& any); 447 448 #define _REGISTER_WXANY_CONVERSION(T, CLASSNAME, FUNC) \ 449 static wxAnyToVariantRegistrationImpl<T> \ 450 gs_##CLASSNAME##AnyToVariantRegistration = \ 451 wxAnyToVariantRegistrationImpl<T>(&FUNC); 452 453 #define REGISTER_WXANY_CONVERSION(T, CLASSNAME) \ 454 _REGISTER_WXANY_CONVERSION(T, CLASSNAME, CLASSNAME::VariantDataFactory) 455 456 #define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME) \ 457 bool CLASSNAME::GetAsAny(wxAny* any) const \ 458 { \ 459 *any = m_value; \ 460 return true; \ 461 } \ 462 wxVariantData* CLASSNAME::VariantDataFactory(const wxAny& any) \ 463 { \ 464 return new CLASSNAME(any.As<T>()); \ 465 } \ 466 REGISTER_WXANY_CONVERSION(T, CLASSNAME) 467 468 #else // if !wxUSE_ANY 469 470 #define DECLARE_WXANY_CONVERSION() 471 #define REGISTER_WXANY_CONVERSION(T, CLASSNAME) 472 #define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME) 473 474 #endif // wxUSE_ANY/!wxUSE_ANY 475 476 477 #define DECLARE_VARIANT_OBJECT(classname) \ 478 DECLARE_VARIANT_OBJECT_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE) 479 480 #define DECLARE_VARIANT_OBJECT_EXPORTED(classname,expdecl) \ 481 expdecl classname& operator << ( classname &object, const wxVariant &variant ); \ 482 expdecl wxVariant& operator << ( wxVariant &variant, const classname &object ); 483 484 #define IMPLEMENT_VARIANT_OBJECT(classname) \ 485 IMPLEMENT_VARIANT_OBJECT_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE) 486 487 #define IMPLEMENT_VARIANT_OBJECT_EXPORTED_NO_EQ(classname,expdecl) \ 488 class classname##VariantData: public wxVariantData \ 489 { \ 490 public:\ 491 classname##VariantData() {} \ 492 classname##VariantData( const classname &value ) : m_value(value) { } \ 493 \ 494 classname &GetValue() { return m_value; } \ 495 \ 496 virtual bool Eq(wxVariantData& data) const wxOVERRIDE; \ 497 \ 498 virtual wxString GetType() const wxOVERRIDE; \ 499 virtual wxClassInfo* GetValueClassInfo() wxOVERRIDE; \ 500 \ 501 virtual wxVariantData* Clone() const wxOVERRIDE { return new classname##VariantData(m_value); } \ 502 \ 503 DECLARE_WXANY_CONVERSION() \ 504 protected:\ 505 classname m_value; \ 506 };\ 507 \ 508 wxString classname##VariantData::GetType() const\ 509 {\ 510 return m_value.GetClassInfo()->GetClassName();\ 511 }\ 512 \ 513 wxClassInfo* classname##VariantData::GetValueClassInfo()\ 514 {\ 515 return m_value.GetClassInfo();\ 516 }\ 517 \ 518 expdecl classname& operator << ( classname &value, const wxVariant &variant )\ 519 {\ 520 wxASSERT( variant.GetType() == #classname );\ 521 \ 522 classname##VariantData *data = (classname##VariantData*) variant.GetData();\ 523 value = data->GetValue();\ 524 return value;\ 525 }\ 526 \ 527 expdecl wxVariant& operator << ( wxVariant &variant, const classname &value )\ 528 {\ 529 classname##VariantData *data = new classname##VariantData( value );\ 530 variant.SetData( data );\ 531 return variant;\ 532 } \ 533 IMPLEMENT_TRIVIAL_WXANY_CONVERSION(classname, classname##VariantData) 534 535 // implements a wxVariantData-derived class using for the Eq() method the 536 // operator== which must have been provided by "classname" 537 #define IMPLEMENT_VARIANT_OBJECT_EXPORTED(classname,expdecl) \ 538 IMPLEMENT_VARIANT_OBJECT_EXPORTED_NO_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl) \ 539 \ 540 bool classname##VariantData::Eq(wxVariantData& data) const \ 541 {\ 542 wxASSERT( GetType() == data.GetType() );\ 543 \ 544 classname##VariantData & otherData = (classname##VariantData &) data;\ 545 \ 546 return otherData.m_value == m_value;\ 547 }\ 548 549 550 // implements a wxVariantData-derived class using for the Eq() method a shallow 551 // comparison (through wxObject::IsSameAs function) 552 #define IMPLEMENT_VARIANT_OBJECT_SHALLOWCMP(classname) \ 553 IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(classname, wxEMPTY_PARAMETER_VALUE) 554 #define IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(classname,expdecl) \ 555 IMPLEMENT_VARIANT_OBJECT_EXPORTED_NO_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl) \ 556 \ 557 bool classname##VariantData::Eq(wxVariantData& data) const \ 558 {\ 559 wxASSERT( GetType() == data.GetType() );\ 560 \ 561 classname##VariantData & otherData = (classname##VariantData &) data;\ 562 \ 563 return (otherData.m_value.IsSameAs(m_value));\ 564 }\ 565 566 567 // Since we want type safety wxVariant we need to fetch and dynamic_cast 568 // in a seemingly safe way so the compiler can check, so we define 569 // a dynamic_cast /wxDynamicCast analogue. 570 571 #define wxGetVariantCast(var,classname) \ 572 ((classname*)(var.IsValueKindOf(&classname::ms_classInfo) ?\ 573 var.GetWxObjectPtr() : NULL)); 574 575 // Replacement for using wxDynamicCast on a wxVariantData object 576 #ifndef wxNO_RTTI 577 #define wxDynamicCastVariantData(data, classname) dynamic_cast<classname*>(data) 578 #endif 579 580 #define wxStaticCastVariantData(data, classname) static_cast<classname*>(data) 581 582 extern wxVariant WXDLLIMPEXP_BASE wxNullVariant; 583 584 #endif // wxUSE_VARIANT 585 586 #endif // _WX_VARIANT_H_ 587