Variant.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/FlyString.h>
  7. #include <AK/JsonValue.h>
  8. #include <AK/RefPtr.h>
  9. #include <LibGUI/Variant.h>
  10. namespace GUI {
  11. const char* to_string(Variant::Type type)
  12. {
  13. switch (type) {
  14. case Variant::Type::Invalid:
  15. return "Invalid";
  16. case Variant::Type::Bool:
  17. return "Bool";
  18. case Variant::Type::Int32:
  19. return "Int32";
  20. case Variant::Type::Int64:
  21. return "Int64";
  22. case Variant::Type::UnsignedInt32:
  23. return "UnsignedInt32";
  24. case Variant::Type::UnsignedInt64:
  25. return "UnsignedInt64";
  26. case Variant::Type::Float:
  27. return "Float";
  28. case Variant::Type::String:
  29. return "String";
  30. case Variant::Type::Bitmap:
  31. return "Bitmap";
  32. case Variant::Type::Color:
  33. return "Color";
  34. case Variant::Type::Icon:
  35. return "Icon";
  36. case Variant::Type::Point:
  37. return "Point";
  38. case Variant::Type::Size:
  39. return "Size";
  40. case Variant::Type::Rect:
  41. return "Rect";
  42. case Variant::Type::Font:
  43. return "Font";
  44. case Variant::Type::TextAlignment:
  45. return "TextAlignment";
  46. }
  47. VERIFY_NOT_REACHED();
  48. }
  49. Variant::Variant()
  50. {
  51. m_value.as_string = nullptr;
  52. }
  53. Variant::~Variant()
  54. {
  55. clear();
  56. }
  57. void Variant::clear()
  58. {
  59. switch (m_type) {
  60. case Type::String:
  61. AK::unref_if_not_null(m_value.as_string);
  62. break;
  63. case Type::Bitmap:
  64. AK::unref_if_not_null(m_value.as_bitmap);
  65. break;
  66. case Type::Icon:
  67. AK::unref_if_not_null(m_value.as_icon);
  68. break;
  69. default:
  70. break;
  71. }
  72. m_type = Type::Invalid;
  73. m_value.as_string = nullptr;
  74. }
  75. Variant::Variant(Gfx::TextAlignment value)
  76. : m_type(Type::TextAlignment)
  77. {
  78. m_value.as_text_alignment = value;
  79. }
  80. Variant::Variant(i32 value)
  81. : m_type(Type::Int32)
  82. {
  83. m_value.as_i32 = value;
  84. }
  85. Variant::Variant(i64 value)
  86. : m_type(Type::Int64)
  87. {
  88. m_value.as_i64 = value;
  89. }
  90. Variant::Variant(u32 value)
  91. : m_type(Type::UnsignedInt32)
  92. {
  93. m_value.as_u32 = value;
  94. }
  95. Variant::Variant(u64 value)
  96. : m_type(Type::UnsignedInt64)
  97. {
  98. m_value.as_u64 = value;
  99. }
  100. Variant::Variant(float value)
  101. : m_type(Type::Float)
  102. {
  103. m_value.as_float = value;
  104. }
  105. Variant::Variant(bool value)
  106. : m_type(Type::Bool)
  107. {
  108. m_value.as_bool = value;
  109. }
  110. Variant::Variant(const char* cstring)
  111. : Variant(String(cstring))
  112. {
  113. }
  114. Variant::Variant(const FlyString& value)
  115. : Variant(String(value.impl()))
  116. {
  117. }
  118. Variant::Variant(const StringView& value)
  119. : Variant(value.to_string())
  120. {
  121. }
  122. Variant::Variant(const String& value)
  123. : m_type(Type::String)
  124. {
  125. m_value.as_string = const_cast<StringImpl*>(value.impl());
  126. AK::ref_if_not_null(m_value.as_string);
  127. }
  128. Variant::Variant(const JsonValue& value)
  129. {
  130. if (value.is_null()) {
  131. m_value.as_string = nullptr;
  132. return;
  133. }
  134. if (value.is_i32()) {
  135. m_type = Type::Int32;
  136. m_value.as_i32 = value.as_i32();
  137. return;
  138. }
  139. if (value.is_u32()) {
  140. m_type = Type::UnsignedInt32;
  141. m_value.as_u32 = value.as_u32();
  142. return;
  143. }
  144. if (value.is_i64()) {
  145. m_type = Type::Int64;
  146. m_value.as_i64 = value.as_i64();
  147. return;
  148. }
  149. if (value.is_u64()) {
  150. m_type = Type::UnsignedInt64;
  151. m_value.as_u64 = value.to_u64();
  152. return;
  153. }
  154. if (value.is_string()) {
  155. m_type = Type::String;
  156. m_value.as_string = value.as_string().impl();
  157. m_value.as_string->ref();
  158. return;
  159. }
  160. if (value.is_bool()) {
  161. m_type = Type::Bool;
  162. m_value.as_bool = value.as_bool();
  163. return;
  164. }
  165. VERIFY_NOT_REACHED();
  166. }
  167. Variant::Variant(const Gfx::Bitmap& value)
  168. : m_type(Type::Bitmap)
  169. {
  170. m_value.as_bitmap = const_cast<Gfx::Bitmap*>(&value);
  171. AK::ref_if_not_null(m_value.as_bitmap);
  172. }
  173. Variant::Variant(const GUI::Icon& value)
  174. : m_type(Type::Icon)
  175. {
  176. m_value.as_icon = &const_cast<GUI::IconImpl&>(value.impl());
  177. AK::ref_if_not_null(m_value.as_icon);
  178. }
  179. Variant::Variant(const Gfx::Font& value)
  180. : m_type(Type::Font)
  181. {
  182. m_value.as_font = &const_cast<Gfx::Font&>(value);
  183. AK::ref_if_not_null(m_value.as_font);
  184. }
  185. Variant::Variant(Color color)
  186. : m_type(Type::Color)
  187. {
  188. m_value.as_color = color.value();
  189. }
  190. Variant::Variant(const Gfx::IntPoint& point)
  191. : m_type(Type::Point)
  192. {
  193. m_value.as_point = { point.x(), point.y() };
  194. }
  195. Variant::Variant(const Gfx::IntSize& size)
  196. : m_type(Type::Size)
  197. {
  198. m_value.as_size = { size.width(), size.height() };
  199. }
  200. Variant::Variant(const Gfx::IntRect& rect)
  201. : m_type(Type::Rect)
  202. {
  203. m_value.as_rect = (const RawRect&)rect;
  204. }
  205. Variant& Variant::operator=(const Variant& other)
  206. {
  207. if (&other == this)
  208. return *this;
  209. clear();
  210. copy_from(other);
  211. return *this;
  212. }
  213. Variant& Variant::operator=(Variant&& other)
  214. {
  215. if (&other == this)
  216. return *this;
  217. clear();
  218. move_from(move(other));
  219. return *this;
  220. }
  221. Variant::Variant(const Variant& other)
  222. {
  223. copy_from(other);
  224. }
  225. void Variant::move_from(Variant&& other)
  226. {
  227. m_type = other.m_type;
  228. m_value = other.m_value;
  229. other.m_type = Type::Invalid;
  230. other.m_value.as_string = nullptr;
  231. }
  232. void Variant::copy_from(const Variant& other)
  233. {
  234. VERIFY(!is_valid());
  235. m_type = other.m_type;
  236. switch (m_type) {
  237. case Type::Bool:
  238. m_value.as_bool = other.m_value.as_bool;
  239. break;
  240. case Type::Int32:
  241. m_value.as_i32 = other.m_value.as_i32;
  242. break;
  243. case Type::Int64:
  244. m_value.as_i64 = other.m_value.as_i64;
  245. break;
  246. case Type::UnsignedInt32:
  247. m_value.as_u32 = other.m_value.as_u32;
  248. break;
  249. case Type::UnsignedInt64:
  250. m_value.as_u64 = other.m_value.as_u64;
  251. break;
  252. case Type::Float:
  253. m_value.as_float = other.m_value.as_float;
  254. break;
  255. case Type::String:
  256. m_value.as_string = other.m_value.as_string;
  257. AK::ref_if_not_null(m_value.as_bitmap);
  258. break;
  259. case Type::Bitmap:
  260. m_value.as_bitmap = other.m_value.as_bitmap;
  261. AK::ref_if_not_null(m_value.as_bitmap);
  262. break;
  263. case Type::Icon:
  264. m_value.as_icon = other.m_value.as_icon;
  265. AK::ref_if_not_null(m_value.as_icon);
  266. break;
  267. case Type::Font:
  268. m_value.as_font = other.m_value.as_font;
  269. AK::ref_if_not_null(m_value.as_font);
  270. break;
  271. case Type::Color:
  272. m_value.as_color = other.m_value.as_color;
  273. break;
  274. case Type::Point:
  275. m_value.as_point = other.m_value.as_point;
  276. break;
  277. case Type::Size:
  278. m_value.as_size = other.m_value.as_size;
  279. break;
  280. case Type::Rect:
  281. m_value.as_rect = other.m_value.as_rect;
  282. break;
  283. case Type::TextAlignment:
  284. m_value.as_text_alignment = other.m_value.as_text_alignment;
  285. break;
  286. case Type::Invalid:
  287. break;
  288. }
  289. }
  290. bool Variant::operator==(const Variant& other) const
  291. {
  292. if (m_type != other.m_type)
  293. return to_string() == other.to_string();
  294. switch (m_type) {
  295. case Type::Bool:
  296. return as_bool() == other.as_bool();
  297. case Type::Int32:
  298. return as_i32() == other.as_i32();
  299. case Type::Int64:
  300. return as_i64() == other.as_i64();
  301. case Type::UnsignedInt32:
  302. return as_u32() == other.as_u32();
  303. case Type::UnsignedInt64:
  304. return as_u64() == other.as_u64();
  305. case Type::Float:
  306. return as_float() == other.as_float();
  307. case Type::String:
  308. return as_string() == other.as_string();
  309. case Type::Bitmap:
  310. return m_value.as_bitmap == other.m_value.as_bitmap;
  311. case Type::Icon:
  312. return m_value.as_icon == other.m_value.as_icon;
  313. case Type::Color:
  314. return m_value.as_color == other.m_value.as_color;
  315. case Type::Point:
  316. return as_point() == other.as_point();
  317. case Type::Size:
  318. return as_size() == other.as_size();
  319. case Type::Rect:
  320. return as_rect() == other.as_rect();
  321. case Type::Font:
  322. return &as_font() == &other.as_font();
  323. case Type::TextAlignment:
  324. return m_value.as_text_alignment == other.m_value.as_text_alignment;
  325. case Type::Invalid:
  326. return true;
  327. }
  328. VERIFY_NOT_REACHED();
  329. }
  330. bool Variant::operator<(const Variant& other) const
  331. {
  332. if (m_type != other.m_type)
  333. return to_string() < other.to_string();
  334. switch (m_type) {
  335. case Type::Bool:
  336. return as_bool() < other.as_bool();
  337. case Type::Int32:
  338. return as_i32() < other.as_i32();
  339. case Type::Int64:
  340. return as_i64() < other.as_i64();
  341. case Type::UnsignedInt32:
  342. return as_u32() < other.as_u32();
  343. case Type::UnsignedInt64:
  344. return as_u64() < other.as_u64();
  345. case Type::Float:
  346. return as_float() < other.as_float();
  347. case Type::String:
  348. return as_string() < other.as_string();
  349. case Type::Bitmap:
  350. // FIXME: Maybe compare bitmaps somehow differently?
  351. return m_value.as_bitmap < other.m_value.as_bitmap;
  352. case Type::Icon:
  353. // FIXME: Maybe compare icons somehow differently?
  354. return m_value.as_icon < other.m_value.as_icon;
  355. case Type::Color:
  356. return m_value.as_color < other.m_value.as_color;
  357. case Type::Point:
  358. case Type::Size:
  359. case Type::Rect:
  360. case Type::Font:
  361. case Type::TextAlignment:
  362. // FIXME: Figure out how to compare these.
  363. VERIFY_NOT_REACHED();
  364. case Type::Invalid:
  365. break;
  366. }
  367. VERIFY_NOT_REACHED();
  368. }
  369. String Variant::to_string() const
  370. {
  371. switch (m_type) {
  372. case Type::Bool:
  373. return as_bool() ? "true" : "false";
  374. case Type::Int32:
  375. return String::number(as_i32());
  376. case Type::Int64:
  377. return String::number(as_i64());
  378. case Type::UnsignedInt32:
  379. return String::number(as_u32());
  380. case Type::UnsignedInt64:
  381. return String::number(as_u64());
  382. case Type::Float:
  383. return String::formatted("{:.2}", as_float());
  384. case Type::String:
  385. return as_string();
  386. case Type::Bitmap:
  387. return "[Gfx::Bitmap]";
  388. case Type::Icon:
  389. return "[GUI::Icon]";
  390. case Type::Color:
  391. return as_color().to_string();
  392. case Type::Point:
  393. return as_point().to_string();
  394. case Type::Size:
  395. return as_size().to_string();
  396. case Type::Rect:
  397. return as_rect().to_string();
  398. case Type::Font:
  399. return String::formatted("[Font: {}]", as_font().name());
  400. case Type::TextAlignment: {
  401. switch (m_value.as_text_alignment) {
  402. case Gfx::TextAlignment::Center:
  403. return "Gfx::TextAlignment::Center";
  404. case Gfx::TextAlignment::CenterLeft:
  405. return "Gfx::TextAlignment::CenterLeft";
  406. case Gfx::TextAlignment::CenterRight:
  407. return "Gfx::TextAlignment::CenterRight";
  408. case Gfx::TextAlignment::TopLeft:
  409. return "Gfx::TextAlignment::TopLeft";
  410. case Gfx::TextAlignment::TopRight:
  411. return "Gfx::TextAlignment::TopRight";
  412. default:
  413. VERIFY_NOT_REACHED();
  414. }
  415. return "";
  416. }
  417. case Type::Invalid:
  418. return "[null]";
  419. }
  420. VERIFY_NOT_REACHED();
  421. }
  422. }