custom_value_traits.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. // Copyright (c) 2016-2021 Thomas Fussell
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE
  20. //
  21. // @license: http://www.opensource.org/licenses/mit-license.php
  22. // @author: see AUTHORS file
  23. #pragma once
  24. #include <algorithm>
  25. #include <string>
  26. #include <unordered_map>
  27. #include <detail/default_case.hpp>
  28. #include <detail/external/include_libstudxml.hpp>
  29. #include <xlnt/packaging/relationship.hpp>
  30. #include <xlnt/styles/alignment.hpp>
  31. #include <xlnt/styles/border.hpp>
  32. #include <xlnt/styles/font.hpp>
  33. #include <xlnt/styles/fill.hpp>
  34. #include <xlnt/utils/exceptions.hpp>
  35. #include <xlnt/utils/variant.hpp>
  36. #include <xlnt/worksheet/pane.hpp>
  37. #include <xlnt/worksheet/page_setup.hpp>
  38. #include <xlnt/workbook/metadata_property.hpp>
  39. namespace xlnt {
  40. namespace detail {
  41. /// <summary>
  42. /// Returns the string representation of the underline style.
  43. /// </summary>
  44. std::string to_string(font::underline_style underline_style);
  45. /// <summary>
  46. /// Returns the string representation of the relationship type.
  47. /// </summary>
  48. std::string to_string(relationship_type t);
  49. std::string to_string(pattern_fill_type fill_type);
  50. std::string to_string(gradient_fill_type fill_type);
  51. std::string to_string(border_style border_style);
  52. std::string to_string(vertical_alignment vertical_alignment);
  53. std::string to_string(horizontal_alignment horizontal_alignment);
  54. std::string to_string(border_side side);
  55. std::string to_string(core_property prop);
  56. std::string to_string(extended_property prop);
  57. std::string to_string(variant::type type);
  58. std::string to_string(pane_corner corner);
  59. std::string to_string(target_mode mode);
  60. std::string to_string(pane_state state);
  61. std::string to_string(orientation state);
  62. template<typename T>
  63. static T from_string(const std::string &string_value);
  64. template<>
  65. font::underline_style from_string(const std::string &string)
  66. {
  67. if (string == "double") return font::underline_style::double_;
  68. if (string == "doubleAccounting") return font::underline_style::double_accounting;
  69. if (string == "single") return font::underline_style::single;
  70. if (string == "singleAccounting") return font::underline_style::single_accounting;
  71. if (string == "none") return font::underline_style::none;
  72. default_case(font::underline_style::none);
  73. }
  74. template<>
  75. relationship_type from_string(const std::string &string)
  76. {
  77. if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")
  78. return relationship_type::office_document;
  79. else if (string == "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail")
  80. return relationship_type::thumbnail;
  81. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain")
  82. return relationship_type::calculation_chain;
  83. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")
  84. return relationship_type::extended_properties;
  85. else if (string == "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
  86. || string == "http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties")
  87. return relationship_type::core_properties;
  88. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet")
  89. return relationship_type::worksheet;
  90. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings")
  91. return relationship_type::shared_string_table;
  92. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles")
  93. return relationship_type::stylesheet;
  94. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme")
  95. return relationship_type::theme;
  96. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")
  97. return relationship_type::hyperlink;
  98. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet")
  99. return relationship_type::chartsheet;
  100. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments")
  101. return relationship_type::comments;
  102. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing")
  103. return relationship_type::vml_drawing;
  104. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")
  105. return relationship_type::custom_properties;
  106. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings")
  107. return relationship_type::printer_settings;
  108. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections")
  109. return relationship_type::connections;
  110. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customProperty")
  111. return relationship_type::custom_property;
  112. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlMappings")
  113. return relationship_type::custom_xml_mappings;
  114. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet")
  115. return relationship_type::dialogsheet;
  116. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing")
  117. return relationship_type::drawings;
  118. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath")
  119. return relationship_type::external_workbook_references;
  120. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable")
  121. return relationship_type::pivot_table;
  122. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition")
  123. return relationship_type::pivot_table_cache_definition;
  124. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords")
  125. return relationship_type::pivot_table_cache_records;
  126. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/queryTable")
  127. return relationship_type::query_table;
  128. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionHeaders")
  129. return relationship_type::shared_workbook_revision_headers;
  130. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedWorkbook")
  131. return relationship_type::shared_workbook;
  132. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionLog")
  133. return relationship_type::revision_log;
  134. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/usernames")
  135. return relationship_type::shared_workbook_user_data;
  136. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableSingleCells")
  137. return relationship_type::single_cell_table_definitions;
  138. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table")
  139. return relationship_type::table_definition;
  140. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/volatileDependencies")
  141. return relationship_type::volatile_dependencies;
  142. else if (string == "http://schemas.microsoft.com/office/2006/relationships/vbaProject")
  143. return relationship_type::vbaproject;
  144. else if (string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")
  145. return relationship_type::image;
  146. // ECMA 376-4 Part 1 Section 9.1.7 says consumers shall not fail to load
  147. // a document with unknown relationships.
  148. return relationship_type::unknown;
  149. }
  150. template<>
  151. pattern_fill_type from_string(const std::string &string)
  152. {
  153. #pragma clang diagnostic push
  154. #pragma clang diagnostic ignored "-Wexit-time-destructors"
  155. static std::unordered_map<std::string, pattern_fill_type> patternFill {
  156. {"darkdown", pattern_fill_type::darkdown },
  157. { "darkgray", pattern_fill_type::darkgray },
  158. { "darkgrid", pattern_fill_type::darkgrid },
  159. { "darkhorizontal", pattern_fill_type::darkhorizontal },
  160. { "darktrellis", pattern_fill_type::darktrellis },
  161. { "darkup", pattern_fill_type::darkup },
  162. { "darkvertical", pattern_fill_type::darkvertical },
  163. { "gray0625", pattern_fill_type::gray0625 },
  164. { "gray125", pattern_fill_type::gray125 },
  165. { "lightdown", pattern_fill_type::lightdown },
  166. { "lightgray", pattern_fill_type::lightgray },
  167. { "lightgrid", pattern_fill_type::lightgrid },
  168. { "lighthorizontal", pattern_fill_type::lighthorizontal },
  169. { "lighttrellis", pattern_fill_type::lighttrellis },
  170. { "lightup", pattern_fill_type::lightup },
  171. { "lightvertical", pattern_fill_type::lightvertical },
  172. { "mediumgray", pattern_fill_type::mediumgray },
  173. { "none", pattern_fill_type::none },
  174. { "solid", pattern_fill_type::solid }
  175. };
  176. #pragma clang diagnostic pop
  177. auto toLower = [](std::string str) {
  178. auto bg = std::begin (str);
  179. auto en = std::end (str);
  180. std::transform(bg, en, bg,
  181. [](char c) {
  182. // static cast to avoid int -> char narrowing warning
  183. return static_cast<char>(tolower(c));
  184. });
  185. return str;
  186. };
  187. auto patternLookup = [](const std::string& key) {
  188. auto entry = patternFill.find (key);
  189. if (entry != std::end (patternFill)) {
  190. return entry->second;
  191. }
  192. else {
  193. // Note: there won't be an error if there is an unsupported pattern
  194. return pattern_fill_type::none;
  195. }
  196. };
  197. std::string lowerString {toLower (string) };
  198. return patternLookup (lowerString);
  199. }
  200. template<>
  201. gradient_fill_type from_string(const std::string &string)
  202. {
  203. if (string == "linear") return gradient_fill_type::linear;
  204. else if (string == "path") return gradient_fill_type::path;
  205. default_case(gradient_fill_type::linear);
  206. }
  207. template<>
  208. border_style from_string(const std::string &string)
  209. {
  210. if (string == "dashDot") return border_style::dashdot;
  211. else if (string == "dashDotDot") return border_style::dashdotdot;
  212. else if (string == "dashed") return border_style::dashed;
  213. else if (string == "dotted") return border_style::dotted;
  214. else if (string == "double") return border_style::double_;
  215. else if (string == "hair") return border_style::hair;
  216. else if (string == "medium") return border_style::medium;
  217. else if (string == "mediumDashdot") return border_style::mediumdashdot;
  218. else if (string == "mediumDashDotDot") return border_style::mediumdashdotdot;
  219. else if (string == "mediumDashed") return border_style::mediumdashed;
  220. else if (string == "none") return border_style::none;
  221. else if (string == "slantDashDot") return border_style::slantdashdot;
  222. else if (string == "thick") return border_style::thick;
  223. else if (string == "thin") return border_style::thin;
  224. default_case(border_style::dashdot);
  225. }
  226. template<>
  227. vertical_alignment from_string(const std::string &string)
  228. {
  229. if (string == "bottom") return vertical_alignment::bottom;
  230. else if (string == "center") return vertical_alignment::center;
  231. else if (string == "distributed") return vertical_alignment::distributed;
  232. else if (string == "justify") return vertical_alignment::justify;
  233. else if (string == "top") return vertical_alignment::top;
  234. default_case(vertical_alignment::top);
  235. }
  236. template<>
  237. horizontal_alignment from_string(const std::string &string)
  238. {
  239. if (string == "center") return horizontal_alignment::center;
  240. else if (string == "centerContinuous") return horizontal_alignment::center_continuous;
  241. else if (string == "distributed") return horizontal_alignment::distributed;
  242. else if (string == "fill") return horizontal_alignment::fill;
  243. else if (string == "general") return horizontal_alignment::general;
  244. else if (string == "justify") return horizontal_alignment::justify;
  245. else if (string == "left") return horizontal_alignment::left;
  246. else if (string == "right") return horizontal_alignment::right;
  247. default_case(horizontal_alignment::general);
  248. }
  249. template<>
  250. border_side from_string(const std::string &string)
  251. {
  252. if (string == "bottom") return border_side::bottom;
  253. else if (string == "diagonal") return border_side::diagonal;
  254. else if (string == "right") return border_side::end;
  255. else if (string == "horizontal") return border_side::horizontal;
  256. else if (string == "left") return border_side::start;
  257. else if (string == "top") return border_side::top;
  258. else if (string == "vertical") return border_side::vertical;
  259. default_case(border_side::bottom);
  260. }
  261. template<>
  262. core_property from_string(const std::string &string)
  263. {
  264. if (string == "category") return core_property::category;
  265. else if (string == "contentStatus") return core_property::content_status;
  266. else if (string == "created") return core_property::created;
  267. else if (string == "creator") return core_property::creator;
  268. else if (string == "description") return core_property::description;
  269. else if (string == "identifier") return core_property::identifier;
  270. else if (string == "keywords") return core_property::keywords;
  271. else if (string == "language") return core_property::language;
  272. else if (string == "lastModifiedBy") return core_property::last_modified_by;
  273. else if (string == "lastPrinted") return core_property::last_printed;
  274. else if (string == "modified") return core_property::modified;
  275. else if (string == "revision") return core_property::revision;
  276. else if (string == "subject") return core_property::subject;
  277. else if (string == "title") return core_property::title;
  278. else if (string == "version") return core_property::version;
  279. default_case(core_property::category);
  280. }
  281. template<>
  282. extended_property from_string(const std::string &string)
  283. {
  284. if (string == "Application") return extended_property::application;
  285. else if (string == "AppVersion") return extended_property::app_version;
  286. else if (string == "Characters") return extended_property::characters;
  287. else if (string == "CharactersWithSpaces") return extended_property::characters_with_spaces;
  288. else if (string == "Company") return extended_property::company;
  289. else if (string == "DigSig") return extended_property::dig_sig;
  290. else if (string == "DocSecurity") return extended_property::doc_security;
  291. else if (string == "HeadingPairs") return extended_property::heading_pairs;
  292. else if (string == "HiddenSlides") return extended_property::hidden_slides;
  293. else if (string == "HyperlinksChanged") return extended_property::hyperlinks_changed;
  294. else if (string == "HyperlinkBase") return extended_property::hyperlink_base;
  295. else if (string == "HLinks") return extended_property::h_links;
  296. else if (string == "Lines") return extended_property::lines;
  297. else if (string == "LinksUpToDate") return extended_property::links_up_to_date;
  298. else if (string == "Manager") return extended_property::manager;
  299. else if (string == "MMClips") return extended_property::m_m_clips;
  300. else if (string == "Notes") return extended_property::notes;
  301. else if (string == "Pages") return extended_property::pages;
  302. else if (string == "Paragraphs") return extended_property::paragraphs;
  303. else if (string == "PresentationFormat") return extended_property::presentation_format;
  304. else if (string == "ScaleCrop") return extended_property::scale_crop;
  305. else if (string == "SharedDoc") return extended_property::shared_doc;
  306. else if (string == "Slides") return extended_property::slides;
  307. else if (string == "Template") return extended_property::template_;
  308. else if (string == "TitlesOfParts") return extended_property::titles_of_parts;
  309. else if (string == "TotalTime") return extended_property::total_time;
  310. else if (string == "Words") return extended_property::words;
  311. default_case(extended_property::application);
  312. }
  313. /*
  314. template<>
  315. variant::type from_string(const std::string &string)
  316. {
  317. if (string == "bool") return variant::type::boolean;
  318. else if (string == "date") return variant::type::date;
  319. else if (string == "i4") return variant::type::i4;
  320. else if (string == "lpstr") return variant::type::lpstr;
  321. else if (string == "null") return variant::type::null;
  322. else if (string == "vector") return variant::type::vector;
  323. default_case(variant::type::null);
  324. }
  325. */
  326. template<>
  327. xlnt::pane_state from_string(const std::string &string)
  328. {
  329. if (string == "frozen") return xlnt::pane_state::frozen;
  330. else if (string == "frozenSplit") return xlnt::pane_state::frozen_split;
  331. else if (string == "split") return xlnt::pane_state::split;
  332. default_case(xlnt::pane_state::frozen);
  333. }
  334. template<>
  335. target_mode from_string(const std::string &string)
  336. {
  337. if (string == "Internal") return target_mode::internal;
  338. else if (string == "External") return target_mode::external;
  339. default_case(target_mode::internal);
  340. }
  341. template<>
  342. pane_corner from_string(const std::string &string)
  343. {
  344. if (string == "bottomLeft") return pane_corner::bottom_left;
  345. else if (string == "bottomRight") return pane_corner::bottom_right;
  346. else if (string == "topLeft") return pane_corner::top_left;
  347. else if (string == "topRight") return pane_corner::top_right;
  348. default_case(pane_corner::bottom_left);
  349. }
  350. template <>
  351. orientation from_string(const std::string &string)
  352. {
  353. if (string == "default") return orientation::default_orientation;
  354. else if (string == "landscape") return orientation::landscape;
  355. else if (string == "portrait") return orientation::portrait;
  356. default_case(orientation::default_orientation);
  357. }
  358. } // namespace detail
  359. } // namespace xlnt
  360. namespace xml {
  361. template <>
  362. struct value_traits<xlnt::font::underline_style>
  363. {
  364. static xlnt::font::underline_style parse(std::string underline_string, const parser &)
  365. {
  366. return xlnt::detail::from_string<xlnt::font::underline_style>(underline_string);
  367. }
  368. static std::string serialize(xlnt::font::underline_style underline_style, const serializer &)
  369. {
  370. return xlnt::detail::to_string(underline_style);
  371. }
  372. };
  373. template <>
  374. struct value_traits<xlnt::relationship_type>
  375. {
  376. static xlnt::relationship_type parse(std::string relationship_type_string, const parser &)
  377. {
  378. return xlnt::detail::from_string<xlnt::relationship_type>(relationship_type_string);
  379. }
  380. static std::string serialize(xlnt::relationship_type type, const serializer &)
  381. {
  382. return xlnt::detail::to_string(type);
  383. }
  384. };
  385. template <>
  386. struct value_traits<xlnt::pattern_fill_type>
  387. {
  388. static xlnt::pattern_fill_type parse(std::string fill_type_string, const parser &)
  389. {
  390. return xlnt::detail::from_string<xlnt::pattern_fill_type>(fill_type_string);
  391. }
  392. static std::string serialize(xlnt::pattern_fill_type fill_type, const serializer &)
  393. {
  394. return xlnt::detail::to_string(fill_type);
  395. }
  396. };
  397. template <>
  398. struct value_traits<xlnt::gradient_fill_type>
  399. {
  400. static xlnt::gradient_fill_type parse(std::string fill_type_string, const parser &)
  401. {
  402. return xlnt::detail::from_string<xlnt::gradient_fill_type>(fill_type_string);
  403. }
  404. static std::string serialize(xlnt::gradient_fill_type fill_type, const serializer &)
  405. {
  406. return xlnt::detail::to_string(fill_type);
  407. }
  408. };
  409. template <>
  410. struct value_traits<xlnt::border_style>
  411. {
  412. static xlnt::border_style parse(std::string style_string, const parser &)
  413. {
  414. return xlnt::detail::from_string<xlnt::border_style>(style_string);
  415. }
  416. static std::string
  417. serialize (xlnt::border_style style, const serializer &)
  418. {
  419. return xlnt::detail::to_string(style);
  420. }
  421. };
  422. template <>
  423. struct value_traits<xlnt::vertical_alignment>
  424. {
  425. static xlnt::vertical_alignment parse(std::string alignment_string, const parser &)
  426. {
  427. return xlnt::detail::from_string<xlnt::vertical_alignment>(alignment_string);
  428. }
  429. static std::string serialize (xlnt::vertical_alignment alignment, const serializer &)
  430. {
  431. return xlnt::detail::to_string(alignment);
  432. }
  433. };
  434. template <>
  435. struct value_traits<xlnt::horizontal_alignment>
  436. {
  437. static xlnt::horizontal_alignment parse(std::string alignment_string, const parser &)
  438. {
  439. return xlnt::detail::from_string<xlnt::horizontal_alignment>(alignment_string);
  440. }
  441. static std::string serialize(xlnt::horizontal_alignment alignment, const serializer &)
  442. {
  443. return xlnt::detail::to_string(alignment);
  444. }
  445. };
  446. template <>
  447. struct value_traits<xlnt::border_side>
  448. {
  449. static xlnt::border_side parse(std::string side_string, const parser &)
  450. {
  451. return xlnt::detail::from_string<xlnt::border_side>(side_string);
  452. }
  453. static std::string serialize(xlnt::border_side side, const serializer &)
  454. {
  455. return xlnt::detail::to_string(side);
  456. }
  457. };
  458. template <>
  459. struct value_traits<xlnt::target_mode>
  460. {
  461. static xlnt::target_mode parse(std::string mode_string, const parser &)
  462. {
  463. return xlnt::detail::from_string<xlnt::target_mode>(mode_string);
  464. }
  465. static std::string serialize(xlnt::target_mode mode, const serializer &)
  466. {
  467. return xlnt::detail::to_string(mode);
  468. }
  469. };
  470. template <>
  471. struct value_traits<xlnt::pane_state>
  472. {
  473. static xlnt::pane_state parse(std::string string, const parser &)
  474. {
  475. return xlnt::detail::from_string<xlnt::pane_state>(string);
  476. }
  477. static std::string serialize(xlnt::pane_state state, const serializer &)
  478. {
  479. return xlnt::detail::to_string(state);
  480. }
  481. };
  482. template <>
  483. struct value_traits<xlnt::pane_corner>
  484. {
  485. static xlnt::pane_corner parse(std::string string, const parser &)
  486. {
  487. return xlnt::detail::from_string<xlnt::pane_corner>(string);
  488. }
  489. static std::string serialize(xlnt::pane_corner corner, const serializer &)
  490. {
  491. return xlnt::detail::to_string(corner);
  492. }
  493. };
  494. template <>
  495. struct value_traits<xlnt::core_property>
  496. {
  497. static xlnt::core_property parse(std::string string, const parser &)
  498. {
  499. return xlnt::detail::from_string<xlnt::core_property>(string);
  500. }
  501. static std::string serialize(xlnt::core_property corner, const serializer &)
  502. {
  503. return xlnt::detail::to_string(corner);
  504. }
  505. };
  506. template <>
  507. struct value_traits<xlnt::extended_property>
  508. {
  509. static xlnt::extended_property parse(std::string string, const parser &)
  510. {
  511. return xlnt::detail::from_string<xlnt::extended_property>(string);
  512. }
  513. static std::string serialize(xlnt::extended_property corner, const serializer &)
  514. {
  515. return xlnt::detail::to_string(corner);
  516. }
  517. };
  518. template <>
  519. struct value_traits<xlnt::orientation>
  520. {
  521. static xlnt::orientation parse(std::string string, const parser &)
  522. {
  523. return xlnt::detail::from_string<xlnt::orientation>(string);
  524. }
  525. static std::string serialize(xlnt::orientation orientation, const serializer &)
  526. {
  527. return xlnt::detail::to_string(orientation);
  528. }
  529. };
  530. } // namespace xml