filesystem 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051
  1. // -*-c++-*-
  2. // vim: set ft=cpp:
  3. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  4. file LICENSE.rst or https://cmake.org/licensing for details. */
  5. #pragma once
  6. #include "cmSTL.hxx" // IWYU pragma: keep
  7. #include <cstdint>
  8. #include <cstring>
  9. #include <iterator>
  10. #include <string>
  11. #include <utility>
  12. #include <cm/string_view>
  13. #include <cm/type_traits>
  14. #include <cmext/iterator>
  15. #if defined(CMake_HAVE_CXX_FILESYSTEM)
  16. # include <filesystem> // IWYU pragma: export
  17. #else
  18. # include <cstddef>
  19. # include <iostream>
  20. # include <memory>
  21. # include <cm/iomanip>
  22. # if defined(_WIN32) && !defined(__CYGWIN__)
  23. # include <algorithm>
  24. # endif
  25. #endif
  26. namespace cm {
  27. namespace filesystem {
  28. #if !defined(CM_FILESYSTEM_SOURCE_TRAITS_ITERATOR)
  29. // Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile
  30. // the source_traits for iterator check. So disable it for now.
  31. # define CM_FILESYSTEM_SOURCE_TRAITS_ITERATOR 0
  32. #endif
  33. namespace internals {
  34. class unicode_helper
  35. {
  36. protected:
  37. using utf8_state = unsigned char;
  38. static utf8_state const s_start = 0;
  39. static utf8_state const s_reject = 8;
  40. static inline bool in_range(std::uint32_t c, std::uint32_t lo,
  41. std::uint32_t hi)
  42. {
  43. return (static_cast<std::uint32_t>(c - lo) < (hi - lo + 1));
  44. }
  45. static inline bool is_surrogate(std::uint32_t c)
  46. {
  47. return in_range(c, 0xd800, 0xdfff);
  48. }
  49. static inline bool is_high_surrogate(std::uint32_t c)
  50. {
  51. return (c & 0xfffffc00) == 0xd800;
  52. }
  53. static inline bool is_low_surrogate(std::uint32_t c)
  54. {
  55. return (c & 0xfffffc00) == 0xdc00;
  56. }
  57. template <typename Char>
  58. static void append(std::basic_string<Char>& str, std::uint32_t codepoint)
  59. {
  60. if (codepoint <= 0x7f) {
  61. str.push_back(static_cast<Char>(codepoint));
  62. } else if (codepoint >= 0x80 && codepoint <= 0x7ff) {
  63. str.push_back(static_cast<Char>((codepoint >> 6) + 192));
  64. str.push_back(static_cast<Char>((codepoint & 0x3f) + 128));
  65. } else if ((codepoint >= 0x800 && codepoint <= 0xd7ff) ||
  66. (codepoint >= 0xe000 && codepoint <= 0xffff)) {
  67. str.push_back(static_cast<Char>((codepoint >> 12) + 224));
  68. str.push_back(static_cast<Char>(((codepoint & 0xfff) >> 6) + 128));
  69. str.push_back(static_cast<Char>((codepoint & 0x3f) + 128));
  70. } else if (codepoint >= 0x10000 && codepoint <= 0x10ffff) {
  71. str.push_back(static_cast<Char>((codepoint >> 18) + 240));
  72. str.push_back(static_cast<Char>(((codepoint & 0x3ffff) >> 12) + 128));
  73. str.push_back(static_cast<Char>(((codepoint & 0xfff) >> 6) + 128));
  74. str.push_back(static_cast<Char>((codepoint & 0x3f) + 128));
  75. } else {
  76. append(str, 0xfffd);
  77. }
  78. }
  79. static utf8_state decode(utf8_state const state, std::uint8_t const fragment,
  80. std::uint32_t& codepoint);
  81. };
  82. template <typename Char, typename = void>
  83. class unicode
  84. {
  85. };
  86. template <typename Char>
  87. class unicode<Char, typename std::enable_if<(sizeof(Char) == 4)>::type>
  88. : public unicode_helper
  89. {
  90. public:
  91. // UTF32 -> UTF8
  92. template <typename UTF8Char>
  93. static std::basic_string<UTF8Char> to_utf8(wchar_t const* str)
  94. {
  95. std::basic_string<UTF8Char> result;
  96. while (auto c = *str++) {
  97. append(result, c);
  98. }
  99. return result;
  100. }
  101. template <typename UTF8Char>
  102. static std::basic_string<UTF8Char> to_utf8(std::wstring const& str)
  103. {
  104. return unicode<Char>::template to_utf8<UTF8Char>(str.c_str());
  105. }
  106. template <typename UTF8Char>
  107. static std::basic_string<UTF8Char> to_utf8(wchar_t c)
  108. {
  109. std::basic_string<UTF8Char> result;
  110. append(result, c);
  111. return result;
  112. }
  113. // UTF8 -> UTF32
  114. template <typename UTF8Char>
  115. static std::wstring from_utf8(UTF8Char const* str, std::size_t length)
  116. {
  117. std::wstring result;
  118. result.reserve(length);
  119. utf8_state state = s_start;
  120. std::uint32_t codepoint = 0;
  121. while (*str) {
  122. if ((state = decode(state, static_cast<std::uint8_t>(*str++),
  123. codepoint)) == s_start) {
  124. result += static_cast<std::wstring::value_type>(codepoint);
  125. codepoint = 0;
  126. } else if (state == s_reject) {
  127. result += static_cast<std::wstring::value_type>(0xfffd);
  128. state = s_start;
  129. codepoint = 0;
  130. }
  131. }
  132. if (state) {
  133. result += static_cast<std::wstring::value_type>(0xfffd);
  134. }
  135. return result;
  136. }
  137. template <typename UTF8Char>
  138. static std::wstring from_utf8(UTF8Char const* str)
  139. {
  140. return unicode<Char>::from_utf8(
  141. str, std::strlen(reinterpret_cast<char const*>(str)));
  142. }
  143. template <typename UTF8Char>
  144. static std::wstring from_utf8(std::basic_string<UTF8Char> const& str)
  145. {
  146. return unicode<Char>::from_utf8(str.c_str(), str.length());
  147. }
  148. template <typename UTF8Char>
  149. static std::wstring from_utf8(UTF8Char c)
  150. {
  151. std::wstring result;
  152. utf8_state state = s_start;
  153. std::uint32_t codepoint = 0;
  154. if ((state = decode(state, static_cast<std::uint8_t>(c), codepoint)) ==
  155. s_start) {
  156. result += static_cast<std::wstring::value_type>(codepoint);
  157. } else {
  158. result += static_cast<std::wstring::value_type>(0xfffd);
  159. }
  160. return result;
  161. }
  162. };
  163. template <typename Char>
  164. class unicode<Char, typename std::enable_if<(sizeof(Char) == 2)>::type>
  165. : public unicode_helper
  166. {
  167. public:
  168. // UTF16 -> UTF8
  169. template <typename UTF8Char>
  170. static std::basic_string<UTF8Char> to_utf8(wchar_t const* str)
  171. {
  172. std::basic_string<UTF8Char> result;
  173. for (; *str; ++str) {
  174. std::uint32_t c = *str;
  175. if (is_surrogate(c)) {
  176. ++str;
  177. if (*str && is_high_surrogate(c) && is_low_surrogate(*str)) {
  178. append(result, (std::uint32_t(c) << 10) + *str - 0x35fdc00);
  179. } else {
  180. append(result, 0xfffd);
  181. if (!*str) {
  182. break;
  183. }
  184. }
  185. } else {
  186. append(result, c);
  187. }
  188. }
  189. return result;
  190. }
  191. template <typename UTF8Char>
  192. static std::basic_string<UTF8Char> to_utf8(std::wstring const& str)
  193. {
  194. return unicode<Char>::template to_utf8<UTF8Char>(str.c_str());
  195. }
  196. template <typename UTF8Char>
  197. static std::basic_string<UTF8Char> to_utf8(wchar_t c)
  198. {
  199. std::basic_string<UTF8Char> result;
  200. if (is_surrogate(c)) {
  201. append(result, 0xfffd);
  202. } else {
  203. append(result, c);
  204. }
  205. return result;
  206. }
  207. // UTF8 -> UTF16
  208. template <typename UTF8Char>
  209. static std::wstring from_utf8(UTF8Char const* str, std::size_t length)
  210. {
  211. std::wstring result;
  212. result.reserve(length);
  213. utf8_state state = s_start;
  214. std::uint32_t codepoint = 0;
  215. while (*str) {
  216. if ((state = decode(state, static_cast<std::uint8_t>(*str++),
  217. codepoint)) == s_start) {
  218. if (codepoint <= 0xffff) {
  219. result += static_cast<std::wstring::value_type>(codepoint);
  220. } else {
  221. codepoint -= 0x10000;
  222. result +=
  223. static_cast<std::wstring::value_type>((codepoint >> 10) + 0xd800);
  224. result += static_cast<std::wstring::value_type>((codepoint & 0x3ff) +
  225. 0xdc00);
  226. }
  227. codepoint = 0;
  228. } else if (state == s_reject) {
  229. result += static_cast<std::wstring::value_type>(0xfffd);
  230. state = s_start;
  231. codepoint = 0;
  232. }
  233. }
  234. if (state) {
  235. result += static_cast<std::wstring::value_type>(0xfffd);
  236. }
  237. return result;
  238. }
  239. template <typename UTF8Char>
  240. static std::wstring from_utf8(UTF8Char const* str)
  241. {
  242. return unicode<Char>::from_utf8(
  243. str, std::strlen(reinterpret_cast<char const*>(str)));
  244. }
  245. template <typename UTF8Char>
  246. static std::wstring from_utf8(std::basic_string<UTF8Char> const& str)
  247. {
  248. return unicode<Char>::from_utf8(str.c_str(), str.length());
  249. }
  250. template <typename UTF8Char>
  251. static std::wstring from_utf8(UTF8Char c)
  252. {
  253. std::wstring result;
  254. utf8_state state = s_start;
  255. std::uint32_t codepoint = 0;
  256. if ((state = decode(state, static_cast<std::uint8_t>(c), codepoint)) ==
  257. s_start) {
  258. if (codepoint <= 0xffff) {
  259. result += static_cast<std::wstring::value_type>(codepoint);
  260. } else {
  261. codepoint -= 0x10000;
  262. result +=
  263. static_cast<std::wstring::value_type>((codepoint >> 10) + 0xd800);
  264. result +=
  265. static_cast<std::wstring::value_type>((codepoint & 0x3ff) + 0xdc00);
  266. }
  267. } else {
  268. result += static_cast<std::wstring::value_type>(0xfffd);
  269. }
  270. return result;
  271. }
  272. };
  273. template <typename In, typename Out>
  274. class unicode_converter;
  275. template <>
  276. class unicode_converter<char, wchar_t>
  277. {
  278. public:
  279. std::wstring operator()(std::string const& in)
  280. {
  281. return unicode<wchar_t>::from_utf8(in);
  282. }
  283. std::wstring operator()(std::string&& in)
  284. {
  285. return unicode<wchar_t>::from_utf8(in);
  286. }
  287. std::wstring operator()(char const* in)
  288. {
  289. return unicode<wchar_t>::from_utf8(in);
  290. }
  291. std::wstring operator()(char in) { return unicode<wchar_t>::from_utf8(in); }
  292. };
  293. template <>
  294. class unicode_converter<wchar_t, char>
  295. {
  296. public:
  297. std::string operator()(std::wstring const& in)
  298. {
  299. return unicode<wchar_t>::to_utf8<char>(in);
  300. }
  301. std::string operator()(std::wstring&& in)
  302. {
  303. return unicode<wchar_t>::to_utf8<char>(in);
  304. }
  305. std::string operator()(wchar_t const* in)
  306. {
  307. return unicode<wchar_t>::to_utf8<char>(in);
  308. }
  309. std::string operator()(wchar_t in)
  310. {
  311. return unicode<wchar_t>::to_utf8<char>(in);
  312. }
  313. };
  314. template <>
  315. class unicode_converter<char, char>
  316. {
  317. public:
  318. std::string operator()(std::string const& in) { return in; }
  319. std::string operator()(std::string&& in) { return in; }
  320. std::string operator()(char const* in) { return std::string(in); }
  321. std::string operator()(char in) { return std::string(1, in); }
  322. };
  323. template <>
  324. class unicode_converter<wchar_t, wchar_t>
  325. {
  326. public:
  327. std::wstring operator()(std::wstring const& in) { return in; }
  328. std::wstring operator()(std::wstring&& in) { return in; }
  329. std::wstring operator()(wchar_t const* in) { return std::wstring(in); }
  330. std::wstring operator()(wchar_t in) { return std::wstring(1, in); }
  331. };
  332. #if defined(__cpp_char8_t)
  333. template <>
  334. class unicode_converter<char, char8_t>
  335. {
  336. public:
  337. std::u8string operator()(std::string const& in)
  338. {
  339. return std::u8string{ reinterpret_cast<char8_t const*>(in.c_str()) };
  340. }
  341. std::u8string operator()(std::string&& in)
  342. {
  343. return std::u8string{ reinterpret_cast<char8_t const*>(in.c_str()) };
  344. }
  345. std::u8string operator()(char const* in)
  346. {
  347. return std::u8string{ reinterpret_cast<char8_t const*>(in) };
  348. }
  349. std::u8string operator()(char in)
  350. {
  351. return std::u8string{ 1, static_cast<char8_t>(in) };
  352. }
  353. };
  354. template <>
  355. class unicode_converter<char8_t, char>
  356. {
  357. public:
  358. std::string operator()(std::u8string const& in)
  359. {
  360. return std::string{ reinterpret_cast<char const*>(in.c_str()) };
  361. }
  362. std::string operator()(std::u8string&& in)
  363. {
  364. return std::string{ reinterpret_cast<char const*>(in.c_str()) };
  365. }
  366. std::string operator()(char8_t const* in)
  367. {
  368. return std::string{ reinterpret_cast<char const*>(in) };
  369. }
  370. std::string operator()(char8_t in)
  371. {
  372. return std::string{ 1, static_cast<char>(in) };
  373. }
  374. };
  375. template <>
  376. class unicode_converter<wchar_t, char8_t>
  377. {
  378. public:
  379. std::u8string operator()(std::wstring const& in)
  380. {
  381. return unicode<wchar_t>::to_utf8<char8_t>(in);
  382. }
  383. std::u8string operator()(std::wstring&& in)
  384. {
  385. return unicode<wchar_t>::to_utf8<char8_t>(in);
  386. }
  387. std::u8string operator()(wchar_t const* in)
  388. {
  389. return unicode<wchar_t>::to_utf8<char8_t>(in);
  390. }
  391. std::u8string operator()(wchar_t in)
  392. {
  393. return unicode<wchar_t>::to_utf8<char8_t>(in);
  394. }
  395. };
  396. template <>
  397. class unicode_converter<char8_t, wchar_t>
  398. {
  399. public:
  400. std::wstring operator()(std::u8string const& in)
  401. {
  402. return unicode<wchar_t>::from_utf8(in);
  403. }
  404. std::wstring operator()(std::u8string&& in)
  405. {
  406. return unicode<wchar_t>::from_utf8(in);
  407. }
  408. std::wstring operator()(char8_t const* in)
  409. {
  410. return unicode<wchar_t>::from_utf8(in);
  411. }
  412. std::wstring operator()(char8_t in)
  413. {
  414. return unicode<wchar_t>::from_utf8(in);
  415. }
  416. };
  417. #endif
  418. template <typename In>
  419. struct string_converter
  420. {
  421. };
  422. template <>
  423. struct string_converter<char>
  424. {
  425. // some compilers, like gcc 4.8 does not implement the following C++11
  426. // signature:
  427. // std::string::string(const string&, const Allocator&)
  428. // As workaround, use char* pointer.
  429. template <typename Char, typename Traits, typename Alloc>
  430. static std::basic_string<Char, Traits, Alloc> to(std::string const& in,
  431. Alloc const& a)
  432. {
  433. return std::basic_string<Char, Traits, Alloc>(
  434. unicode_converter<char, Char>()(in).c_str(), a);
  435. }
  436. template <typename Char, typename Traits, typename Alloc>
  437. static std::basic_string<Char, Traits, Alloc> to(char const* in,
  438. Alloc const& a)
  439. {
  440. return std::basic_string<Char, Traits, Alloc>(
  441. unicode_converter<char, Char>()(in).c_str(), a);
  442. }
  443. template <typename Char, typename Traits, typename Alloc>
  444. static std::basic_string<Char, Traits, Alloc> to(char in, Alloc const& a)
  445. {
  446. return std::basic_string<Char, Traits, Alloc>(
  447. unicode_converter<char, Char>()(in).c_str(), a);
  448. }
  449. template <typename Char>
  450. static std::basic_string<Char> to(std::string const& in)
  451. {
  452. return std::basic_string<Char>(unicode_converter<char, Char>()(in));
  453. }
  454. template <typename Char>
  455. static std::basic_string<Char> to(std::string&& in)
  456. {
  457. return std::basic_string<Char>(
  458. unicode_converter<char, Char>()(std::move(in)));
  459. }
  460. template <typename Char>
  461. static std::basic_string<Char> to(cm::string_view in)
  462. {
  463. return std::basic_string<Char>(
  464. unicode_converter<char, Char>()(std::string{ in.begin(), in.end() }));
  465. }
  466. template <typename Char>
  467. static std::basic_string<Char> to(char const* in)
  468. {
  469. return std::basic_string<Char>(unicode_converter<char, Char>()(in));
  470. }
  471. template <typename Char>
  472. static std::basic_string<Char> to(char in)
  473. {
  474. return std::basic_string<Char>(unicode_converter<char, Char>()(in));
  475. }
  476. template <typename Char, typename Iterator>
  477. static std::basic_string<Char> to(Iterator it)
  478. {
  479. char e = '\0';
  480. std::string tmp;
  481. for (; *it != e; ++it) {
  482. tmp.push_back(*it);
  483. }
  484. return std::basic_string<Char>(
  485. unicode_converter<char, Char>()(std::move(tmp)));
  486. }
  487. template <typename Char, typename Iterator>
  488. static std::basic_string<Char> to(Iterator begin, Iterator end)
  489. {
  490. return std::basic_string<Char>(
  491. unicode_converter<char, Char>()(std::string{ begin, end }));
  492. }
  493. };
  494. template <>
  495. struct string_converter<wchar_t>
  496. {
  497. // some compilers, like gcc 4.8 does not implement the following C++11
  498. // signature:
  499. // std::string::string(const string&, const Allocator&)
  500. // As workaround, use char* pointer.
  501. template <typename Char, typename Traits, typename Alloc>
  502. static std::basic_string<Char, Traits, Alloc> to(std::wstring const& in,
  503. Alloc const& a)
  504. {
  505. return std::basic_string<Char, Traits, Alloc>(
  506. unicode_converter<wchar_t, Char>()(in).c_str(), a);
  507. }
  508. template <typename Char, typename Traits, typename Alloc>
  509. static std::basic_string<Char, Traits, Alloc> to(wchar_t const* in,
  510. Alloc const& a)
  511. {
  512. return std::basic_string<Char, Traits, Alloc>(
  513. unicode_converter<wchar_t, Char>()(in).c_str(), a);
  514. }
  515. template <typename Char, typename Traits, typename Alloc>
  516. static std::basic_string<Char, Traits, Alloc> to(wchar_t in, Alloc const& a)
  517. {
  518. return std::basic_string<Char, Traits, Alloc>(
  519. unicode_converter<wchar_t, Char>()(in).c_str(), a);
  520. }
  521. template <typename Char>
  522. static std::basic_string<Char> to(std::wstring const& in)
  523. {
  524. return std::basic_string<Char>(unicode_converter<wchar_t, Char>()(in));
  525. }
  526. template <typename Char>
  527. static std::basic_string<Char> to(std::wstring&& in)
  528. {
  529. return std::basic_string<Char>(
  530. unicode_converter<wchar_t, Char>()(std::move(in)));
  531. }
  532. template <typename Char>
  533. static std::basic_string<Char> to(wchar_t const* in)
  534. {
  535. return std::basic_string<Char>(unicode_converter<wchar_t, Char>()(in));
  536. }
  537. template <typename Char>
  538. static std::basic_string<Char> to(wchar_t in)
  539. {
  540. return std::basic_string<Char>(unicode_converter<wchar_t, Char>()(in));
  541. }
  542. template <typename Char, typename Iterator>
  543. static std::basic_string<Char> to(Iterator it)
  544. {
  545. wchar_t e = '\0';
  546. std::wstring tmp;
  547. for (; *it != e; ++it) {
  548. tmp.push_back(*it);
  549. }
  550. return std::basic_string<Char>(
  551. unicode_converter<wchar_t, Char>()(std::move(tmp)));
  552. }
  553. template <typename Char, typename Iterator>
  554. static std::basic_string<Char> to(Iterator begin, Iterator end)
  555. {
  556. return std::basic_string<Char>(
  557. unicode_converter<wchar_t, Char>()(std::wstring{ begin, end }));
  558. }
  559. };
  560. #if defined(__cpp_char8_t)
  561. template <>
  562. struct string_converter<char8_t>
  563. {
  564. // some compilers, like gcc 4.8 does not implement the following C++11
  565. // signature:
  566. // std::string::string(const string&, const Allocator&)
  567. // As workaround, use char* pointer.
  568. template <typename Char, typename Traits, typename Alloc>
  569. static std::basic_string<Char, Traits, Alloc> to(std::u8string const& in,
  570. Alloc const& a)
  571. {
  572. return std::basic_string<Char, Traits, Alloc>(
  573. unicode_converter<char8_t, Char>()(in).c_str(), a);
  574. }
  575. template <typename Char, typename Traits, typename Alloc>
  576. static std::basic_string<Char, Traits, Alloc> to(char8_t const* in,
  577. Alloc const& a)
  578. {
  579. return std::basic_string<Char, Traits, Alloc>(
  580. unicode_converter<char8_t, Char>()(in).c_str(), a);
  581. }
  582. template <typename Char, typename Traits, typename Alloc>
  583. static std::basic_string<Char, Traits, Alloc> to(char8_t in, Alloc const& a)
  584. {
  585. return std::basic_string<Char, Traits, Alloc>(
  586. unicode_converter<char8_t, Char>()(in).c_str(), a);
  587. }
  588. template <typename Char>
  589. static std::basic_string<Char> to(std::u8string const& in)
  590. {
  591. return std::basic_string<Char>(unicode_converter<char8_t, Char>()(in));
  592. }
  593. template <typename Char>
  594. static std::basic_string<Char> to(std::u8string&& in)
  595. {
  596. return std::basic_string<Char>(
  597. unicode_converter<char8_t, Char>()(std::move(in)));
  598. }
  599. template <typename Char>
  600. static std::basic_string<Char> to(char8_t const* in)
  601. {
  602. return std::basic_string<Char>(unicode_converter<char8_t, Char>()(in));
  603. }
  604. template <typename Char>
  605. static std::basic_string<Char> to(char8_t in)
  606. {
  607. return std::basic_string<Char>(unicode_converter<char8_t, Char>()(in));
  608. }
  609. template <typename Char, typename Iterator>
  610. static std::basic_string<Char> to(Iterator it)
  611. {
  612. char8_t e = '\0';
  613. std::u8string tmp;
  614. for (; *it != e; ++it) {
  615. tmp.push_back(*it);
  616. }
  617. return std::basic_string<Char>(
  618. unicode_converter<char8_t, Char>()(std::move(tmp)));
  619. }
  620. template <typename Char, typename Iterator>
  621. static std::basic_string<Char> to(Iterator begin, Iterator end)
  622. {
  623. return std::basic_string<Char>(
  624. unicode_converter<char8_t, Char>()(std::u8string{ begin, end }));
  625. }
  626. };
  627. #endif
  628. template <typename T, typename = void>
  629. struct source_traits
  630. {
  631. };
  632. template <typename T, std::size_t N>
  633. struct source_traits<T[N]>
  634. {
  635. using value_type = T;
  636. };
  637. template <typename T>
  638. struct source_traits<T*>
  639. {
  640. using value_type = cm::decay_t<T>;
  641. };
  642. template <typename Char, typename Traits, typename Alloc>
  643. struct source_traits<std::basic_string<Char, Traits, Alloc>>
  644. {
  645. using value_type =
  646. typename std::basic_string<Char, Traits, Alloc>::value_type;
  647. };
  648. template <>
  649. struct source_traits<cm::string_view>
  650. {
  651. using value_type = cm::string_view::value_type;
  652. };
  653. #if CM_FILESYSTEM_SOURCE_TRAITS_ITERATOR
  654. template <typename T>
  655. struct source_traits<T, cm::enable_if_t<cm::is_iterator<T>::value, void>>
  656. {
  657. using value_type =
  658. typename std::iterator_traits<typename std::decay<T>::type>::value_type;
  659. };
  660. #endif
  661. template <typename T>
  662. struct is_pathable_string : std::false_type
  663. {
  664. };
  665. template <typename Traits, typename Alloc>
  666. struct is_pathable_string<std::basic_string<char, Traits, Alloc>>
  667. : std::true_type
  668. {
  669. };
  670. template <typename Traits, typename Alloc>
  671. struct is_pathable_string<std::basic_string<wchar_t, Traits, Alloc>>
  672. : std::true_type
  673. {
  674. };
  675. template <>
  676. struct is_pathable_string<cm::string_view> : std::true_type
  677. {
  678. };
  679. template <typename T, typename = void>
  680. struct is_pathable_char_array : std::false_type
  681. {
  682. };
  683. template <typename T>
  684. struct is_pathable_char_array<
  685. T,
  686. cm::enable_if_t<
  687. std::is_same<char*, typename std::decay<T>::type>::value ||
  688. std::is_same<wchar_t*, typename std::decay<T>::type>::value,
  689. void>>
  690. : bool_constant<std::is_same<char*, typename std::decay<T>::type>::value ||
  691. std::is_same<wchar_t*, typename std::decay<T>::type>::value>
  692. {
  693. };
  694. template <typename T, typename = void>
  695. struct is_pathable_iterator : std::false_type
  696. {
  697. };
  698. template <typename T>
  699. struct is_pathable_iterator<
  700. T,
  701. cm::enable_if_t<
  702. is_input_iterator<T>::value &&
  703. (std::is_same<char,
  704. typename std::iterator_traits<
  705. typename std::decay<T>::type>::value_type>::value ||
  706. std::is_same<wchar_t,
  707. typename std::iterator_traits<
  708. typename std::decay<T>::type>::value_type>::value),
  709. void>>
  710. : bool_constant<
  711. std::is_same<char,
  712. typename std::iterator_traits<
  713. typename std::decay<T>::type>::value_type>::value ||
  714. std::is_same<wchar_t,
  715. typename std::iterator_traits<
  716. typename std::decay<T>::type>::value_type>::value>
  717. {
  718. };
  719. #if defined(__SUNPRO_CC) && defined(__sparc)
  720. // Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile
  721. // the full 'is_pathable' check. We use it only to improve error messages
  722. // via 'enable_if' when calling methods with incorrect types. Just
  723. // pretend all types are allowed so we can at least compile valid code.
  724. template <typename T>
  725. struct is_pathable : std::true_type
  726. {
  727. };
  728. #else
  729. template <typename T>
  730. struct is_pathable
  731. : bool_constant<is_pathable_string<T>::value ||
  732. is_pathable_char_array<T>::value ||
  733. is_pathable_iterator<T>::value>
  734. {
  735. };
  736. #endif
  737. template <typename In, typename Out>
  738. struct source_converter
  739. {
  740. };
  741. template <>
  742. struct source_converter<char, char>
  743. {
  744. template <typename Iterator>
  745. static void append_range(std::string& p, Iterator b, Iterator e)
  746. {
  747. if (b == e) {
  748. return;
  749. }
  750. p.append(b, e);
  751. }
  752. template <typename Iterator>
  753. static void append_range(std::string& p, Iterator b)
  754. {
  755. char e = '\0';
  756. if (*b == e) {
  757. return;
  758. }
  759. for (; *b != e; ++b) {
  760. p.push_back(*b);
  761. }
  762. }
  763. static void append_source(std::string& p, cm::string_view s)
  764. {
  765. append_range(p, s.begin(), s.end());
  766. }
  767. static void append_source(std::string& p, std::string const& s)
  768. {
  769. append_range(p, s.begin(), s.end());
  770. }
  771. template <typename Source>
  772. static void append_source(std::string& p, Source const& s)
  773. {
  774. append_range(p, s);
  775. }
  776. static void set_source(std::string& p, std::string&& s) { p = std::move(s); }
  777. static std::string from(cm::string_view s)
  778. {
  779. return std::string{ s.begin(), s.end() };
  780. }
  781. static std::string from(std::string const& s) { return s; }
  782. static std::string from(std::string&& s) { return s; }
  783. template <typename Source>
  784. static std::string from(Source const& s)
  785. {
  786. std::string result;
  787. append_source(result, s);
  788. return result;
  789. }
  790. template <typename Iterator>
  791. static std::string from(Iterator first, Iterator last)
  792. {
  793. return std::string{ first, last };
  794. }
  795. };
  796. template <>
  797. struct source_converter<char, wchar_t>
  798. {
  799. static std::wstring from(std::string const& s)
  800. {
  801. return string_converter<char>::to<wchar_t>(s);
  802. }
  803. static std::wstring from(std::string&& s)
  804. {
  805. return string_converter<char>::to<wchar_t>(std::move(s));
  806. }
  807. template <typename Source>
  808. static std::wstring from(Source const& s)
  809. {
  810. return string_converter<char>::to<wchar_t>(s);
  811. }
  812. template <typename Iterator>
  813. static std::wstring from(Iterator first, Iterator last)
  814. {
  815. return string_converter<char>::to<wchar_t>(first, last);
  816. }
  817. };
  818. template <>
  819. struct source_converter<wchar_t, wchar_t>
  820. {
  821. template <typename Iterator>
  822. static void append_range(std::wstring& p, Iterator b, Iterator e)
  823. {
  824. if (b == e) {
  825. return;
  826. }
  827. p.append(b, e);
  828. }
  829. template <typename Iterator>
  830. static void append_range(std::wstring& p, Iterator b)
  831. {
  832. char e = '\0';
  833. if (*b == e) {
  834. return;
  835. }
  836. for (; *b != e; ++b) {
  837. p.push_back(*b);
  838. }
  839. }
  840. template <typename Source>
  841. static void append_source(std::wstring& p, Source const& s)
  842. {
  843. append_range(p, s);
  844. }
  845. static std::wstring from(std::wstring const& s) { return s; }
  846. static std::wstring from(std::wstring&& s) { return s; }
  847. template <typename Source>
  848. static std::wstring from(Source const& s)
  849. {
  850. std::wstring result;
  851. append_source(result, s);
  852. return result;
  853. }
  854. template <typename Iterator>
  855. static std::wstring from(Iterator first, Iterator last)
  856. {
  857. return std::wstring{ first, last };
  858. }
  859. };
  860. template <>
  861. struct source_converter<wchar_t, char>
  862. {
  863. template <typename Iterator>
  864. static void append_range(std::string& p, Iterator b, Iterator e)
  865. {
  866. if (b == e) {
  867. return;
  868. }
  869. std::string dest = string_converter<wchar_t>::to<char>(b, e);
  870. p.append(dest.begin(), dest.end());
  871. }
  872. template <typename Iterator>
  873. static void append_range(std::string& p, Iterator b)
  874. {
  875. wchar_t e = '\0';
  876. if (*b == e) {
  877. return;
  878. }
  879. std::string dest = string_converter<wchar_t>::to<char>(b);
  880. p.append(dest.begin(), dest.end());
  881. }
  882. static void append_source(std::string& p, std::wstring const& s)
  883. {
  884. append_range(p, s.begin(), s.end());
  885. }
  886. template <typename Source>
  887. static void append_source(std::string& p, Source const& s)
  888. {
  889. append_range(p, s);
  890. }
  891. static void set_source(std::string& p, std::wstring&& s)
  892. {
  893. p = string_converter<wchar_t>::to<char>(std::move(s));
  894. }
  895. static std::string from(std::wstring const& s)
  896. {
  897. return string_converter<wchar_t>::to<char>(s);
  898. }
  899. static std::string from(std::wstring&& s)
  900. {
  901. return string_converter<wchar_t>::to<char>(std::move(s));
  902. }
  903. template <typename Source>
  904. static std::string from(Source const& s)
  905. {
  906. return string_converter<wchar_t>::to<char>(s);
  907. }
  908. template <typename Iterator>
  909. static std::string from(Iterator first, Iterator last)
  910. {
  911. return string_converter<wchar_t>::to<char>(first, last);
  912. }
  913. };
  914. #if defined(__cpp_char8_t)
  915. template <>
  916. struct source_converter<char, char8_t>
  917. {
  918. static std::u8string from(std::string const& s)
  919. {
  920. return string_converter<char>::to<char8_t>(s);
  921. }
  922. static std::u8string from(std::string&& s)
  923. {
  924. return string_converter<char>::to<char8_t>(std::move(s));
  925. }
  926. template <typename Source>
  927. static std::u8string from(Source const& s)
  928. {
  929. return string_converter<char>::to<char8_t>(s);
  930. }
  931. template <typename Iterator>
  932. static std::u8string from(Iterator first, Iterator last)
  933. {
  934. return string_converter<char>::to<char8_t>(first, last);
  935. }
  936. };
  937. template <>
  938. struct source_converter<char8_t, char>
  939. {
  940. static std::string from(std::u8string const& s)
  941. {
  942. return string_converter<char8_t>::to<char>(s);
  943. }
  944. static std::string from(std::u8string&& s)
  945. {
  946. return string_converter<char8_t>::to<char>(std::move(s));
  947. }
  948. template <typename Source>
  949. static std::string from(Source const& s)
  950. {
  951. return string_converter<char8_t>::to<char>(s);
  952. }
  953. template <typename Iterator>
  954. static std::string from(Iterator first, Iterator last)
  955. {
  956. return string_converter<char8_t>::to<char>(first, last);
  957. }
  958. };
  959. template <>
  960. struct source_converter<wchar_t, char8_t>
  961. {
  962. static std::u8string from(std::wstring const& s)
  963. {
  964. return string_converter<wchar_t>::to<char8_t>(s);
  965. }
  966. static std::u8string from(std::wstring&& s)
  967. {
  968. return string_converter<wchar_t>::to<char8_t>(std::move(s));
  969. }
  970. template <typename Source>
  971. static std::u8string from(Source const& s)
  972. {
  973. return string_converter<wchar_t>::to<char8_t>(s);
  974. }
  975. template <typename Iterator>
  976. static std::u8string from(Iterator first, Iterator last)
  977. {
  978. return string_converter<wchar_t>::to<char8_t>(first, last);
  979. }
  980. };
  981. template <>
  982. struct source_converter<char8_t, wchar_t>
  983. {
  984. static std::wstring from(std::u8string const& s)
  985. {
  986. return string_converter<char8_t>::to<wchar_t>(s);
  987. }
  988. static std::wstring from(std::u8string&& s)
  989. {
  990. return string_converter<char8_t>::to<wchar_t>(std::move(s));
  991. }
  992. template <typename Source>
  993. static std::wstring from(Source const& s)
  994. {
  995. return string_converter<char8_t>::to<wchar_t>(s);
  996. }
  997. template <typename Iterator>
  998. static std::wstring from(Iterator first, Iterator last)
  999. {
  1000. return string_converter<char8_t>::to<wchar_t>(first, last);
  1001. }
  1002. };
  1003. #endif
  1004. }
  1005. #if defined(CMake_HAVE_CXX_FILESYSTEM)
  1006. class path : public std::filesystem::path
  1007. {
  1008. private:
  1009. using base = std::filesystem::path;
  1010. // define the char type to convert to
  1011. # if defined(__cpp_char8_t) && defined(_WIN32) && !defined(__CYGWIN__)
  1012. using target_type = char8_t;
  1013. # else
  1014. using target_type = base::value_type;
  1015. # endif
  1016. template <typename Source>
  1017. using enable_if_pathable =
  1018. enable_if_t<filesystem::internals::is_pathable<Source>::value, path&>;
  1019. template <typename Source, typename Target = target_type>
  1020. using string_converter = filesystem::internals::source_converter<
  1021. typename filesystem::internals::source_traits<Source>::value_type, Target>;
  1022. template <typename Iterator, typename Target = target_type>
  1023. using range_converter = filesystem::internals::source_converter<
  1024. typename std::iterator_traits<Iterator>::value_type, Target>;
  1025. public:
  1026. class iterator;
  1027. using const_iterator = iterator;
  1028. // Constructors
  1029. // ============
  1030. path() noexcept {}
  1031. path(path const& p)
  1032. : base(p)
  1033. {
  1034. }
  1035. path(path&& p) noexcept
  1036. : base(std::move(p))
  1037. {
  1038. }
  1039. path(string_type&& source, format fmt = format::auto_format)
  1040. : base(string_converter<string_type>::from(std::move(source)), fmt)
  1041. {
  1042. }
  1043. template <typename Source, typename = enable_if_pathable<Source>>
  1044. path(Source const& source, format fmt = format::auto_format)
  1045. : base(string_converter<Source>::from(source), fmt)
  1046. {
  1047. }
  1048. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1049. path(Iterator first, Iterator last, format fmt = format::auto_format)
  1050. : base(range_converter<Iterator>::from(first, last), fmt)
  1051. {
  1052. }
  1053. ~path() = default;
  1054. // Assignments
  1055. // ===========
  1056. path& operator=(path const& p)
  1057. {
  1058. if (this != &p) {
  1059. this->base::operator=(static_cast<base const&>(p));
  1060. }
  1061. return *this;
  1062. }
  1063. path& operator=(path&& p) noexcept
  1064. {
  1065. if (this != &p) {
  1066. this->base::operator=(std::move(static_cast<base&&>(p)));
  1067. }
  1068. return *this;
  1069. }
  1070. path& operator=(string_type&& source)
  1071. {
  1072. return this->assign(std::move(source));
  1073. }
  1074. template <typename Source, typename = enable_if_pathable<Source>>
  1075. path& operator=(Source const& source)
  1076. {
  1077. return this->assign(source);
  1078. }
  1079. path& assign(string_type&& source)
  1080. {
  1081. this->base::assign(string_converter<string_type>::from(std::move(source)));
  1082. return *this;
  1083. }
  1084. template <typename Source, typename = enable_if_pathable<Source>>
  1085. path& assign(Source const& source)
  1086. {
  1087. this->base::assign(string_converter<Source>::from(source));
  1088. return *this;
  1089. }
  1090. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1091. path& assign(Iterator first, Iterator last)
  1092. {
  1093. this->base::assign(range_converter<Iterator>::from(first, last));
  1094. return *this;
  1095. }
  1096. // Concatenation
  1097. // =============
  1098. path& operator/=(path const& p)
  1099. {
  1100. this->base::operator/=(static_cast<base const&>(p));
  1101. return *this;
  1102. }
  1103. template <typename Source>
  1104. path& operator/=(Source const& source)
  1105. {
  1106. return this->append(source);
  1107. }
  1108. template <typename Source, typename = enable_if_pathable<Source>>
  1109. path& append(Source const& source)
  1110. {
  1111. this->base::append(string_converter<Source>::from(source));
  1112. return *this;
  1113. }
  1114. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1115. path& append(Iterator first, Iterator last)
  1116. {
  1117. this->base::append(range_converter<Iterator>::from(first, last));
  1118. return *this;
  1119. }
  1120. path& operator+=(path const& p)
  1121. {
  1122. this->base::operator+=(static_cast<base const&>(p));
  1123. return *this;
  1124. }
  1125. path& operator+=(string_type const& str) { return this->concat(str); }
  1126. path& operator+=(cm::string_view str)
  1127. {
  1128. this->concat(str.begin(), str.end());
  1129. return *this;
  1130. }
  1131. path& operator+=(value_type const* str) { return this->concat(str); }
  1132. path& operator+=(value_type const c)
  1133. {
  1134. return this->concat(string_type{ 1, c });
  1135. }
  1136. template <typename Source>
  1137. path& operator+=(Source const& source)
  1138. {
  1139. return this->concat(source);
  1140. }
  1141. template <typename Source, typename = enable_if_pathable<Source>>
  1142. path& concat(Source const& source)
  1143. {
  1144. this->base::concat(string_converter<Source>::from(source));
  1145. return *this;
  1146. }
  1147. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1148. path& concat(Iterator first, Iterator last)
  1149. {
  1150. this->base::concat(range_converter<Iterator>::from(first, last));
  1151. return *this;
  1152. }
  1153. // Format observers
  1154. // ================
  1155. string_type const& native() const noexcept
  1156. {
  1157. # if defined(_WIN32) && !defined(__CYGWIN__)
  1158. this->native_path_ = this->wstring();
  1159. return this->native_path_;
  1160. # else
  1161. return this->base::native();
  1162. # endif
  1163. }
  1164. value_type const* c_str() const noexcept { return this->native().c_str(); }
  1165. operator string_type() const { return this->native(); }
  1166. std::string string() const
  1167. {
  1168. # if defined(_WIN32) && !defined(__CYGWIN__)
  1169. # if defined(__cpp_char8_t)
  1170. return string_converter<std::u8string, std::string::value_type>::from(
  1171. this->base::u8string());
  1172. # else
  1173. return string_converter<std::wstring, std::string::value_type>::from(
  1174. this->base::wstring());
  1175. # endif
  1176. # else
  1177. return this->base::string();
  1178. # endif
  1179. }
  1180. std::wstring wstring() const { return this->base::wstring(); }
  1181. # if defined(__cpp_char8_t)
  1182. std::u8string u8string() const
  1183. # else
  1184. std::string u8string() const
  1185. # endif
  1186. {
  1187. # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__cpp_char8_t)
  1188. return string_converter<std::wstring, std::string::value_type>::from(
  1189. this->base::wstring());
  1190. # else
  1191. return this->base::u8string();
  1192. # endif
  1193. }
  1194. std::string generic_string() const
  1195. {
  1196. # if defined(_WIN32) && !defined(__CYGWIN__)
  1197. # if defined(__cpp_char8_t)
  1198. return string_converter<std::u8string, std::string::value_type>::from(
  1199. this->base::generic_u8string());
  1200. # else
  1201. return string_converter<std::wstring, std::string::value_type>::from(
  1202. this->base::generic_wstring());
  1203. # endif
  1204. # else
  1205. return this->base::generic_string();
  1206. # endif
  1207. }
  1208. std::wstring generic_wstring() const
  1209. {
  1210. return this->base::generic_wstring();
  1211. }
  1212. # if defined(__cpp_char8_t)
  1213. std::u8string generic_u8string() const
  1214. # else
  1215. std::string generic_u8string() const
  1216. # endif
  1217. {
  1218. # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__cpp_char8_t)
  1219. return string_converter<std::wstring, std::string::value_type>::from(
  1220. this->base::generic_wstring());
  1221. # else
  1222. return this->base::generic_u8string();
  1223. # endif
  1224. }
  1225. // Generation
  1226. // ==========
  1227. path lexically_normal() const { return this->base::lexically_normal(); }
  1228. path lexically_relative(path const& root) const
  1229. {
  1230. return this->base::lexically_relative(root);
  1231. }
  1232. path lexically_proximate(path const& root) const
  1233. {
  1234. return this->base::lexically_proximate(root);
  1235. }
  1236. // Decomposition
  1237. // =============
  1238. path root_name() const { return this->base::root_name(); }
  1239. path root_directory() const { return this->base::root_directory(); }
  1240. path root_path() const { return this->base::root_path(); }
  1241. path relative_path() const { return this->base::relative_path(); }
  1242. path parent_path() const { return this->base::parent_path(); }
  1243. path filename() const { return this->base::filename(); }
  1244. path stem() const { return this->base::stem(); }
  1245. path extension() const { return this->base::extension(); }
  1246. // Iterators
  1247. // =========
  1248. inline iterator begin() const;
  1249. inline iterator end() const;
  1250. // Non-members
  1251. // ===========
  1252. friend inline path operator/(path const& lhs, path const& rhs)
  1253. {
  1254. path result{ lhs };
  1255. result /= rhs;
  1256. return result;
  1257. }
  1258. private:
  1259. friend class iterator;
  1260. path(base&& p)
  1261. : base(std::move(p))
  1262. {
  1263. }
  1264. mutable string_type native_path_;
  1265. };
  1266. class path::iterator
  1267. {
  1268. public:
  1269. using iterator_category = std::filesystem::path::iterator::iterator_category;
  1270. using value_type = path;
  1271. using difference_type = std::filesystem::path::iterator::difference_type;
  1272. using pointer = path const*;
  1273. using reference = path const&;
  1274. iterator() = default;
  1275. iterator(iterator const& other)
  1276. : iterator_(other.iterator_)
  1277. {
  1278. }
  1279. ~iterator() = default;
  1280. iterator& operator=(iterator const& other)
  1281. {
  1282. this->iterator_ = other.iterator_;
  1283. return *this;
  1284. }
  1285. reference operator*() const
  1286. {
  1287. this->path_element_ = path{ *this->iterator_ };
  1288. return this->path_element_;
  1289. }
  1290. pointer operator->() const
  1291. {
  1292. this->path_element_ = path{ *this->iterator_ };
  1293. return &this->path_element_;
  1294. }
  1295. iterator& operator++()
  1296. {
  1297. this->iterator_++;
  1298. return *this;
  1299. }
  1300. iterator operator++(int)
  1301. {
  1302. iterator it(*this);
  1303. this->operator++();
  1304. return *this;
  1305. }
  1306. iterator& operator--()
  1307. {
  1308. this->iterator_--;
  1309. return *this;
  1310. }
  1311. iterator operator--(int)
  1312. {
  1313. iterator it(*this);
  1314. this->operator--();
  1315. return it;
  1316. }
  1317. private:
  1318. friend class path;
  1319. friend bool operator==(iterator const&, iterator const&);
  1320. iterator(std::filesystem::path::iterator it)
  1321. : iterator_(it)
  1322. {
  1323. }
  1324. std::filesystem::path::iterator iterator_;
  1325. mutable path path_element_;
  1326. };
  1327. inline path::iterator path::begin() const
  1328. {
  1329. return iterator{ this->base::begin() };
  1330. }
  1331. inline path::iterator path::end() const
  1332. {
  1333. return iterator{ this->base::end() };
  1334. }
  1335. // Non-member functions
  1336. // ====================
  1337. inline bool operator==(path::iterator const& lhs, path::iterator const& rhs)
  1338. {
  1339. return lhs.iterator_ == rhs.iterator_;
  1340. }
  1341. inline bool operator!=(path::iterator const& lhs, path::iterator const& rhs)
  1342. {
  1343. return !(lhs == rhs);
  1344. }
  1345. inline void swap(path& lhs, path& rhs) noexcept
  1346. {
  1347. lhs.swap(rhs);
  1348. }
  1349. inline std::size_t hash_value(path const& p) noexcept
  1350. {
  1351. return std::filesystem::hash_value(p);
  1352. }
  1353. #else
  1354. namespace internals {
  1355. class path_parser;
  1356. }
  1357. class path
  1358. {
  1359. protected:
  1360. using path_type = std::string;
  1361. template <typename Source>
  1362. using enable_if_pathable =
  1363. enable_if_t<internals::is_pathable<Source>::value, path&>;
  1364. enum class filename_fragment : unsigned char
  1365. {
  1366. stem,
  1367. extension
  1368. };
  1369. public:
  1370. # if defined(_WIN32) && !defined(__CYGWIN__)
  1371. using value_type = wchar_t;
  1372. # else
  1373. using value_type = char;
  1374. # endif
  1375. using string_type = std::basic_string<value_type>;
  1376. class iterator;
  1377. using const_iterator = iterator;
  1378. enum format : unsigned char
  1379. {
  1380. auto_format,
  1381. native_format,
  1382. generic_format
  1383. };
  1384. # if defined(_WIN32) && !defined(__CYGWIN__)
  1385. static constexpr value_type preferred_separator = L'\\';
  1386. # else
  1387. static constexpr value_type preferred_separator = '/';
  1388. # endif
  1389. // Constructors
  1390. // ============
  1391. path() noexcept {}
  1392. path(path const& p)
  1393. : path_(p.path_)
  1394. {
  1395. }
  1396. path(path&& p) noexcept
  1397. : path_(std::move(p.path_))
  1398. {
  1399. }
  1400. path(string_type&& source, format fmt = auto_format)
  1401. {
  1402. (void)fmt;
  1403. internals::source_converter<value_type, path_type::value_type>::set_source(
  1404. this->path_, std::move(source));
  1405. }
  1406. template <typename Source, typename = enable_if_pathable<Source>>
  1407. path(Source const& source, format fmt = auto_format)
  1408. {
  1409. (void)fmt;
  1410. internals::source_converter<
  1411. typename internals::source_traits<Source>::value_type,
  1412. path_type::value_type>::append_source(this->path_, source);
  1413. }
  1414. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1415. path(Iterator first, Iterator last, format fmt = auto_format)
  1416. {
  1417. (void)fmt;
  1418. internals::source_converter<
  1419. typename std::iterator_traits<Iterator>::value_type,
  1420. path_type::value_type>::append_range(this->path_, first, last);
  1421. }
  1422. ~path() = default;
  1423. // Assignments
  1424. // ===========
  1425. path& operator=(path const& p)
  1426. {
  1427. if (this != &p) {
  1428. this->path_ = p.path_;
  1429. }
  1430. return *this;
  1431. }
  1432. path& operator=(path&& p) noexcept
  1433. {
  1434. if (this != &p) {
  1435. this->path_ = std::move(p.path_);
  1436. }
  1437. return *this;
  1438. }
  1439. path& operator=(string_type&& source)
  1440. {
  1441. return this->assign(std::move(source));
  1442. }
  1443. template <typename Source, typename = enable_if_pathable<Source>>
  1444. path& operator=(Source const& source)
  1445. {
  1446. return this->assign(source);
  1447. }
  1448. path& assign(string_type&& source)
  1449. {
  1450. internals::source_converter<value_type, path_type::value_type>::set_source(
  1451. this->path_, std::move(source));
  1452. return *this;
  1453. }
  1454. template <typename Source, typename = enable_if_pathable<Source>>
  1455. path& assign(Source const& source)
  1456. {
  1457. this->path_.clear();
  1458. internals::source_converter<
  1459. typename internals::source_traits<Source>::value_type,
  1460. path_type::value_type>::append_source(this->path_, source);
  1461. return *this;
  1462. }
  1463. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1464. path& assign(Iterator first, Iterator last)
  1465. {
  1466. this->path_.clear();
  1467. internals::source_converter<
  1468. typename std::iterator_traits<Iterator>::value_type,
  1469. path_type::value_type>::append_range(this->path_, first, last);
  1470. return *this;
  1471. }
  1472. // Concatenation
  1473. // =============
  1474. path& operator/=(path const& p);
  1475. template <typename Source, typename = enable_if_pathable<Source>>
  1476. path& append(Source const& source)
  1477. {
  1478. return this->operator/=(path(source));
  1479. }
  1480. template <typename Source>
  1481. path& operator/=(Source const& source)
  1482. {
  1483. return this->append(source);
  1484. }
  1485. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1486. path& append(Iterator first, Iterator last)
  1487. {
  1488. return this->operator/=(path(first, last));
  1489. }
  1490. path& operator+=(path const& p)
  1491. {
  1492. this->path_ += p.path_;
  1493. return *this;
  1494. }
  1495. path& operator+=(string_type const& str)
  1496. {
  1497. this->path_ +=
  1498. internals::string_converter<value_type>::to<path_type::value_type>(str);
  1499. return *this;
  1500. }
  1501. path& operator+=(cm::string_view str)
  1502. {
  1503. this->path_.append(str.begin(), str.end());
  1504. return *this;
  1505. }
  1506. path& operator+=(value_type const* str)
  1507. {
  1508. this->path_ +=
  1509. internals::string_converter<value_type>::to<path_type::value_type>(str);
  1510. return *this;
  1511. }
  1512. path& operator+=(value_type const c)
  1513. {
  1514. this->path_ +=
  1515. internals::string_converter<value_type>::to<path_type::value_type>(c);
  1516. return *this;
  1517. }
  1518. template <typename Source, typename = enable_if_pathable<Source>>
  1519. path& concat(Source const& source)
  1520. {
  1521. internals::source_converter<
  1522. typename internals::source_traits<Source>::value_type,
  1523. path_type::value_type>::append_source(this->path_, source);
  1524. return *this;
  1525. }
  1526. template <typename Source>
  1527. path& operator+=(Source const& source)
  1528. {
  1529. return this->concat(source);
  1530. }
  1531. template <typename Iterator, typename = enable_if_pathable<Iterator>>
  1532. path& concat(Iterator first, Iterator last)
  1533. {
  1534. internals::source_converter<
  1535. typename std::iterator_traits<Iterator>::value_type,
  1536. path_type::value_type>::append_range(this->path_, first, last);
  1537. return *this;
  1538. }
  1539. // Modifiers
  1540. // =========
  1541. void clear() noexcept { this->path_.clear(); }
  1542. path& make_preferred()
  1543. {
  1544. # if defined(_WIN32) && !defined(__CYGWIN__)
  1545. std::replace(
  1546. this->path_.begin(), this->path_.end(), '/',
  1547. static_cast<path_type::value_type>(this->preferred_separator));
  1548. # endif
  1549. return *this;
  1550. }
  1551. path& remove_filename()
  1552. {
  1553. auto fname = this->get_filename();
  1554. if (!fname.empty()) {
  1555. this->path_.erase(fname.data() -
  1556. // Avoid C++17 non-const .data() that may reallocate.
  1557. static_cast<path_type const&>(this->path_).data());
  1558. }
  1559. return *this;
  1560. }
  1561. path& replace_filename(path const& replacement)
  1562. {
  1563. this->remove_filename();
  1564. this->operator/=(replacement);
  1565. return *this;
  1566. }
  1567. path& replace_extension(path const& replacement = path())
  1568. {
  1569. auto ext = this->get_filename_fragment(filename_fragment::extension);
  1570. if (!ext.empty()) {
  1571. this->path_.erase(ext.data() -
  1572. // Avoid C++17 non-const .data() that may reallocate.
  1573. static_cast<path_type const&>(this->path_).data());
  1574. }
  1575. if (!replacement.path_.empty()) {
  1576. if (replacement.path_[0] != '.') {
  1577. this->path_ += '.';
  1578. }
  1579. this->path_.append(replacement.path_);
  1580. }
  1581. return *this;
  1582. }
  1583. void swap(path& other) noexcept { this->path_.swap(other.path_); }
  1584. // Format observers
  1585. // ================
  1586. string_type const& native() const noexcept
  1587. {
  1588. # if defined(_WIN32) && !defined(__CYGWIN__)
  1589. this->native_path_ = internals::string_converter<
  1590. path_type::value_type>::to<string_type::value_type>(this->path_);
  1591. return this->native_path_;
  1592. # else
  1593. return this->path_;
  1594. # endif
  1595. }
  1596. value_type const* c_str() const noexcept { return this->native().c_str(); }
  1597. operator string_type() const { return this->native(); }
  1598. template <
  1599. typename Char, typename Traits = std::char_traits<Char>,
  1600. typename Alloc = std::allocator<Char>,
  1601. cm::enable_if_t<(std::is_same<Char, char>::value &&
  1602. std::is_same<Traits, std::char_traits<char>>::value) ||
  1603. (std::is_same<Char, wchar_t>::value &&
  1604. std::is_same<Traits, std::char_traits<wchar_t>>::value),
  1605. int> = 1>
  1606. std::basic_string<Char, Traits, Alloc> string(Alloc const& a = Alloc()) const
  1607. {
  1608. return internals::string_converter<path_type::value_type>::to<Char, Traits,
  1609. Alloc>(
  1610. this->path_, a);
  1611. }
  1612. std::string string() const { return this->path_; }
  1613. std::wstring wstring() const
  1614. {
  1615. return internals::string_converter<path_type::value_type>::to<
  1616. std::wstring::value_type>(this->string());
  1617. }
  1618. std::string u8string() const { return this->path_; }
  1619. template <
  1620. typename Char, typename Traits = std::char_traits<Char>,
  1621. typename Alloc = std::allocator<Char>,
  1622. cm::enable_if_t<(std::is_same<Char, char>::value &&
  1623. std::is_same<Traits, std::char_traits<char>>::value) ||
  1624. (std::is_same<Char, wchar_t>::value &&
  1625. std::is_same<Traits, std::char_traits<wchar_t>>::value),
  1626. int> = 1>
  1627. std::basic_string<Char, Traits, Alloc> generic_string(
  1628. Alloc const& a = Alloc()) const
  1629. {
  1630. return internals::string_converter<path_type::value_type>::to<Char, Traits,
  1631. Alloc>(
  1632. this->get_generic(), a);
  1633. }
  1634. std::string generic_string() const { return this->get_generic(); }
  1635. std::wstring generic_wstring() const
  1636. {
  1637. return internals::string_converter<path_type::value_type>::to<
  1638. std::wstring::value_type>(this->generic_string());
  1639. }
  1640. std::string generic_u8string() const { return this->get_generic(); }
  1641. // Compare
  1642. // =======
  1643. int compare(path const& p) const noexcept
  1644. {
  1645. return this->compare_path(p.path_);
  1646. }
  1647. int compare(string_type const& str) const
  1648. {
  1649. return this->compare_path(
  1650. internals::string_converter<value_type>::to<path_type::value_type>(str));
  1651. }
  1652. int compare(value_type const* str) const
  1653. {
  1654. return this->compare_path(
  1655. internals::string_converter<value_type>::to<path_type::value_type>(str));
  1656. }
  1657. int compare(cm::string_view str) const { return this->compare_path(str); }
  1658. // Generation
  1659. // ==========
  1660. path lexically_normal() const;
  1661. path lexically_relative(path const& base) const;
  1662. path lexically_proximate(path const& base) const
  1663. {
  1664. path result = this->lexically_relative(base);
  1665. return result.empty() ? *this : result;
  1666. }
  1667. // Decomposition
  1668. // =============
  1669. path root_name() const { return get_root_name(); }
  1670. path root_directory() const { return this->get_root_directory(); }
  1671. path root_path() const
  1672. {
  1673. return this->root_name().append(this->get_root_directory());
  1674. }
  1675. path relative_path() const { return this->get_relative_path(); }
  1676. path parent_path() const { return this->get_parent_path(); }
  1677. path filename() const { return this->get_filename(); }
  1678. path stem() const
  1679. {
  1680. return this->get_filename_fragment(filename_fragment::stem);
  1681. }
  1682. path extension() const
  1683. {
  1684. return this->get_filename_fragment(filename_fragment::extension);
  1685. }
  1686. // Queries
  1687. // =======
  1688. bool empty() const noexcept { return this->path_.empty(); }
  1689. bool has_root_name() const { return !this->get_root_name().empty(); }
  1690. bool has_root_directory() const
  1691. {
  1692. return !this->get_root_directory().empty();
  1693. }
  1694. bool has_root_path() const
  1695. {
  1696. return this->has_root_name() || this->has_root_directory();
  1697. }
  1698. bool has_relative_path() const { return !this->get_relative_path().empty(); }
  1699. bool has_parent_path() const { return !this->get_parent_path().empty(); }
  1700. bool has_filename() const { return !this->get_filename().empty(); }
  1701. bool has_stem() const
  1702. {
  1703. return !this->get_filename_fragment(filename_fragment::stem).empty();
  1704. }
  1705. bool has_extension() const
  1706. {
  1707. return !this->get_filename_fragment(filename_fragment::extension).empty();
  1708. }
  1709. bool is_absolute() const
  1710. {
  1711. # if defined(_WIN32) && !defined(__CYGWIN__)
  1712. return this->has_root_name() && this->has_root_directory();
  1713. # else
  1714. // For CYGWIN, root_name (i.e. //host or /cygdrive/x) is not considered.
  1715. // Same as current GNU g++ implementation (9.3).
  1716. return this->has_root_directory();
  1717. # endif
  1718. }
  1719. bool is_relative() const { return !this->is_absolute(); }
  1720. // Iterators
  1721. // =========
  1722. inline iterator begin() const;
  1723. inline iterator end() const;
  1724. // Non-members
  1725. // ===========
  1726. friend inline bool operator==(path const& lhs, path const& rhs) noexcept
  1727. {
  1728. return lhs.compare(rhs) == 0;
  1729. }
  1730. friend inline bool operator!=(path const& lhs, path const& rhs) noexcept
  1731. {
  1732. return lhs.compare(rhs) != 0;
  1733. }
  1734. friend inline bool operator<(path const& lhs, path const& rhs) noexcept
  1735. {
  1736. return lhs.compare(rhs) < 0;
  1737. }
  1738. friend inline bool operator<=(path const& lhs, path const& rhs) noexcept
  1739. {
  1740. return lhs.compare(rhs) <= 0;
  1741. }
  1742. friend inline bool operator>(path const& lhs, path const& rhs) noexcept
  1743. {
  1744. return lhs.compare(rhs) > 0;
  1745. }
  1746. friend inline bool operator>=(path const& lhs, path const& rhs) noexcept
  1747. {
  1748. return lhs.compare(rhs) >= 0;
  1749. }
  1750. friend inline path operator/(path const& lhs, path const& rhs)
  1751. {
  1752. path result(lhs);
  1753. result /= rhs;
  1754. return result;
  1755. }
  1756. template <typename Char, typename Traits>
  1757. friend inline cm::enable_if_t<
  1758. (std::is_same<Char, path::value_type>::value &&
  1759. std::is_same<Traits, std::char_traits<path::value_type>>::value) ||
  1760. (std::is_same<Char, path::path_type::value_type>::value &&
  1761. std::is_same<Traits,
  1762. std::char_traits<path::path_type::value_type>>::value),
  1763. std::basic_ostream<Char, Traits>&>
  1764. operator<<(std::basic_ostream<Char, Traits>& os, path const& p)
  1765. {
  1766. os << cm::quoted(p.string<Char, Traits>());
  1767. return os;
  1768. }
  1769. template <typename Char, typename Traits>
  1770. friend inline cm::enable_if_t<
  1771. (std::is_same<Char, path::value_type>::value &&
  1772. std::is_same<Traits, std::char_traits<path::value_type>>::value) ||
  1773. (std::is_same<Char, path::path_type::value_type>::value &&
  1774. std::is_same<Traits,
  1775. std::char_traits<path::path_type::value_type>>::value),
  1776. std::basic_istream<Char, Traits>&>
  1777. operator>>(std::basic_istream<Char, Traits>& is, path& p)
  1778. {
  1779. std::basic_string<Char, Traits> tmp;
  1780. is >> cm::quoted(tmp);
  1781. p = tmp;
  1782. return is;
  1783. }
  1784. private:
  1785. friend class iterator;
  1786. friend std::size_t hash_value(path const& p) noexcept;
  1787. path_type get_generic() const;
  1788. cm::string_view get_root_name() const;
  1789. cm::string_view get_root_directory() const;
  1790. cm::string_view get_relative_path() const;
  1791. cm::string_view get_parent_path() const;
  1792. cm::string_view get_filename() const;
  1793. cm::string_view get_filename_fragment(filename_fragment fragment) const;
  1794. int compare_path(cm::string_view str) const;
  1795. path_type path_;
  1796. # if defined(_WIN32) && !defined(__CYGWIN__)
  1797. mutable string_type native_path_;
  1798. # endif
  1799. };
  1800. class path::iterator
  1801. {
  1802. public:
  1803. using iterator_category = std::bidirectional_iterator_tag;
  1804. using value_type = path;
  1805. using difference_type = std::ptrdiff_t;
  1806. using pointer = path const*;
  1807. using reference = path const&;
  1808. iterator();
  1809. iterator(iterator const& other);
  1810. ~iterator();
  1811. iterator& operator=(iterator const& other);
  1812. reference operator*() const { return this->path_element_; }
  1813. pointer operator->() const { return &this->path_element_; }
  1814. iterator& operator++();
  1815. iterator operator++(int)
  1816. {
  1817. iterator it(*this);
  1818. this->operator++();
  1819. return it;
  1820. }
  1821. iterator& operator--();
  1822. iterator operator--(int)
  1823. {
  1824. iterator it(*this);
  1825. this->operator--();
  1826. return it;
  1827. }
  1828. private:
  1829. friend class path;
  1830. friend bool operator==(iterator const&, iterator const&);
  1831. iterator(path const* p, bool at_end = false);
  1832. path const* path_;
  1833. std::unique_ptr<internals::path_parser> parser_;
  1834. path path_element_;
  1835. };
  1836. inline path::iterator path::begin() const
  1837. {
  1838. return iterator(this);
  1839. }
  1840. inline path::iterator path::end() const
  1841. {
  1842. return iterator(this, true);
  1843. }
  1844. // Non-member functions
  1845. // ====================
  1846. bool operator==(path::iterator const& lhs, path::iterator const& rhs);
  1847. inline bool operator!=(path::iterator const& lhs, path::iterator const& rhs)
  1848. {
  1849. return !(lhs == rhs);
  1850. }
  1851. inline void swap(path& lhs, path& rhs) noexcept
  1852. {
  1853. lhs.swap(rhs);
  1854. }
  1855. std::size_t hash_value(path const& p) noexcept;
  1856. #endif
  1857. } // namespace filesystem
  1858. } // namespace cm