Serenity Operating System
at portability 419 lines 11 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/JsonValue.h> 28#include <LibGUI/Variant.h> 29 30namespace GUI { 31 32const char* to_string(Variant::Type type) 33{ 34 switch (type) { 35 case Variant::Type::Invalid: 36 return "Invalid"; 37 case Variant::Type::Bool: 38 return "Bool"; 39 case Variant::Type::Int32: 40 return "Int32"; 41 case Variant::Type::Int64: 42 return "Int64"; 43 case Variant::Type::UnsignedInt: 44 return "UnsignedInt"; 45 case Variant::Type::Float: 46 return "Float"; 47 case Variant::Type::String: 48 return "String"; 49 case Variant::Type::Bitmap: 50 return "Bitmap"; 51 case Variant::Type::Color: 52 return "Color"; 53 case Variant::Type::Icon: 54 return "Icon"; 55 case Variant::Type::Point: 56 return "Point"; 57 case Variant::Type::Size: 58 return "Size"; 59 case Variant::Type::Rect: 60 return "Rect"; 61 case Variant::Type::Font: 62 return "Font"; 63 } 64 ASSERT_NOT_REACHED(); 65} 66 67Variant::Variant() 68{ 69 m_value.as_string = nullptr; 70} 71 72Variant::~Variant() 73{ 74 clear(); 75} 76 77void Variant::clear() 78{ 79 switch (m_type) { 80 case Type::String: 81 AK::unref_if_not_null(m_value.as_string); 82 break; 83 case Type::Bitmap: 84 AK::unref_if_not_null(m_value.as_bitmap); 85 break; 86 case Type::Icon: 87 AK::unref_if_not_null(m_value.as_icon); 88 break; 89 default: 90 break; 91 } 92 m_type = Type::Invalid; 93 m_value.as_string = nullptr; 94} 95 96Variant::Variant(i32 value) 97 : m_type(Type::Int32) 98{ 99 m_value.as_i32 = value; 100} 101 102Variant::Variant(i64 value) 103 : m_type(Type::Int64) 104{ 105 m_value.as_i64 = value; 106} 107 108Variant::Variant(unsigned value) 109 : m_type(Type::UnsignedInt) 110{ 111 m_value.as_uint = value; 112} 113 114Variant::Variant(float value) 115 : m_type(Type::Float) 116{ 117 m_value.as_float = value; 118} 119 120Variant::Variant(bool value) 121 : m_type(Type::Bool) 122{ 123 m_value.as_bool = value; 124} 125 126Variant::Variant(const char* cstring) 127 : Variant(String(cstring)) 128{ 129} 130 131Variant::Variant(const String& value) 132 : m_type(Type::String) 133{ 134 m_value.as_string = const_cast<StringImpl*>(value.impl()); 135 AK::ref_if_not_null(m_value.as_string); 136} 137 138Variant::Variant(const JsonValue& value) 139{ 140 if (value.is_null()) { 141 m_value.as_string = nullptr; 142 return; 143 } 144 145 if (value.is_i32()) { 146 m_type = Type::Int32; 147 m_value.as_i32 = value.as_i32(); 148 return; 149 } 150 151 if (value.is_u32()) { 152 m_type = Type::UnsignedInt; 153 m_value.as_uint = value.as_u32(); 154 return; 155 } 156 157 if (value.is_i64()) { 158 m_type = Type::Int64; 159 m_value.as_i64 = value.as_i64(); 160 return; 161 } 162 163 if (value.is_u64()) { 164 // FIXME: Variant should have a 64-bit internal type. 165 m_type = Type::UnsignedInt; 166 m_value.as_uint = value.to_u32(); 167 return; 168 } 169 170 if (value.is_string()) { 171 m_type = Type::String; 172 m_value.as_string = value.as_string().impl(); 173 m_value.as_string->ref(); 174 return; 175 } 176 177 if (value.is_bool()) { 178 m_type = Type::Bool; 179 m_value.as_bool = value.as_bool(); 180 return; 181 } 182 183 ASSERT_NOT_REACHED(); 184} 185 186Variant::Variant(const Gfx::Bitmap& value) 187 : m_type(Type::Bitmap) 188{ 189 m_value.as_bitmap = const_cast<Gfx::Bitmap*>(&value); 190 AK::ref_if_not_null(m_value.as_bitmap); 191} 192 193Variant::Variant(const GIcon& value) 194 : m_type(Type::Icon) 195{ 196 m_value.as_icon = &const_cast<GIconImpl&>(value.impl()); 197 AK::ref_if_not_null(m_value.as_icon); 198} 199 200Variant::Variant(const Gfx::Font& value) 201 : m_type(Type::Font) 202{ 203 m_value.as_font = &const_cast<Gfx::Font&>(value); 204 AK::ref_if_not_null(m_value.as_font); 205} 206 207Variant::Variant(Color color) 208 : m_type(Type::Color) 209{ 210 m_value.as_color = color.value(); 211} 212 213Variant::Variant(const Gfx::Point& point) 214 : m_type(Type::Point) 215{ 216 m_value.as_point = { point.x(), point.y() }; 217} 218 219Variant::Variant(const Gfx::Size& size) 220 : m_type(Type::Size) 221{ 222 m_value.as_size = { size.width(), size.height() }; 223} 224 225Variant::Variant(const Gfx::Rect& rect) 226 : m_type(Type::Rect) 227{ 228 m_value.as_rect = (const RawRect&)rect; 229} 230 231Variant& Variant::operator=(const Variant& other) 232{ 233 if (&other == this) 234 return *this; 235 clear(); 236 copy_from(other); 237 return *this; 238} 239 240Variant& Variant::operator=(Variant&& other) 241{ 242 if (&other == this) 243 return *this; 244 // FIXME: Move, not copy! 245 clear(); 246 copy_from(other); 247 other.clear(); 248 return *this; 249} 250 251Variant::Variant(const Variant& other) 252{ 253 copy_from(other); 254} 255 256void Variant::copy_from(const Variant& other) 257{ 258 ASSERT(!is_valid()); 259 m_type = other.m_type; 260 switch (m_type) { 261 case Type::Bool: 262 m_value.as_bool = other.m_value.as_bool; 263 break; 264 case Type::Int32: 265 m_value.as_i32 = other.m_value.as_i32; 266 break; 267 case Type::Int64: 268 m_value.as_i64 = other.m_value.as_i64; 269 break; 270 case Type::UnsignedInt: 271 m_value.as_uint = other.m_value.as_uint; 272 break; 273 case Type::Float: 274 m_value.as_float = other.m_value.as_float; 275 break; 276 case Type::String: 277 m_value.as_string = other.m_value.as_string; 278 AK::ref_if_not_null(m_value.as_bitmap); 279 break; 280 case Type::Bitmap: 281 m_value.as_bitmap = other.m_value.as_bitmap; 282 AK::ref_if_not_null(m_value.as_bitmap); 283 break; 284 case Type::Icon: 285 m_value.as_icon = other.m_value.as_icon; 286 AK::ref_if_not_null(m_value.as_icon); 287 break; 288 case Type::Font: 289 m_value.as_font = other.m_value.as_font; 290 AK::ref_if_not_null(m_value.as_font); 291 break; 292 case Type::Color: 293 m_value.as_color = other.m_value.as_color; 294 break; 295 case Type::Point: 296 m_value.as_point = other.m_value.as_point; 297 break; 298 case Type::Size: 299 m_value.as_size = other.m_value.as_size; 300 break; 301 case Type::Rect: 302 m_value.as_rect = other.m_value.as_rect; 303 break; 304 case Type::Invalid: 305 break; 306 } 307} 308 309bool Variant::operator==(const Variant& other) const 310{ 311 if (m_type != other.m_type) 312 return to_string() == other.to_string(); 313 switch (m_type) { 314 case Type::Bool: 315 return as_bool() == other.as_bool(); 316 case Type::Int32: 317 return as_i32() == other.as_i32(); 318 case Type::Int64: 319 return as_i64() == other.as_i64(); 320 case Type::UnsignedInt: 321 return as_uint() == other.as_uint(); 322 case Type::Float: 323 return as_float() == other.as_float(); 324 case Type::String: 325 return as_string() == other.as_string(); 326 case Type::Bitmap: 327 return m_value.as_bitmap == other.m_value.as_bitmap; 328 case Type::Icon: 329 return m_value.as_icon == other.m_value.as_icon; 330 case Type::Color: 331 return m_value.as_color == other.m_value.as_color; 332 case Type::Point: 333 return as_point() == other.as_point(); 334 case Type::Size: 335 return as_size() == other.as_size(); 336 case Type::Rect: 337 return as_rect() == other.as_rect(); 338 case Type::Font: 339 return &as_font() == &other.as_font(); 340 case Type::Invalid: 341 return true; 342 } 343 ASSERT_NOT_REACHED(); 344} 345 346bool Variant::operator<(const Variant& other) const 347{ 348 if (m_type != other.m_type) 349 return to_string() < other.to_string(); 350 switch (m_type) { 351 case Type::Bool: 352 return as_bool() < other.as_bool(); 353 case Type::Int32: 354 return as_i32() < other.as_i32(); 355 case Type::Int64: 356 return as_i64() < other.as_i64(); 357 case Type::UnsignedInt: 358 return as_uint() < other.as_uint(); 359 case Type::Float: 360 return as_float() < other.as_float(); 361 case Type::String: 362 return as_string() < other.as_string(); 363 case Type::Bitmap: 364 // FIXME: Maybe compare bitmaps somehow differently? 365 return m_value.as_bitmap < other.m_value.as_bitmap; 366 case Type::Icon: 367 // FIXME: Maybe compare icons somehow differently? 368 return m_value.as_icon < other.m_value.as_icon; 369 case Type::Color: 370 return m_value.as_color < other.m_value.as_color; 371 case Type::Point: 372 case Type::Size: 373 case Type::Rect: 374 case Type::Font: 375 // FIXME: Figure out how to compare these. 376 ASSERT_NOT_REACHED(); 377 case Type::Invalid: 378 break; 379 } 380 ASSERT_NOT_REACHED(); 381} 382 383String Variant::to_string() const 384{ 385 switch (m_type) { 386 case Type::Bool: 387 return as_bool() ? "true" : "false"; 388 case Type::Int32: 389 return String::number(as_i32()); 390 case Type::Int64: 391 return String::number(as_i64()); 392 case Type::UnsignedInt: 393 return String::number(as_uint()); 394 case Type::Float: 395 return String::format("%f", (double)as_float()); 396 case Type::String: 397 return as_string(); 398 case Type::Bitmap: 399 return "[Gfx::Bitmap]"; 400 case Type::Icon: 401 return "[GIcon]"; 402 case Type::Color: 403 return as_color().to_string(); 404 case Type::Point: 405 return as_point().to_string(); 406 case Type::Size: 407 return as_size().to_string(); 408 case Type::Rect: 409 return as_rect().to_string(); 410 case Type::Font: 411 return String::format("[Font: %s]", as_font().name().characters()); 412 case Type::Invalid: 413 return "[null]"; 414 break; 415 } 416 ASSERT_NOT_REACHED(); 417} 418 419}