| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456 |
- //---------------------------------------------------------------------------------------
- //
- // ghc::filesystem - A C++17-like filesystem implementation for
- // C++11/C++14/C++17
- //
- //---------------------------------------------------------------------------------------
- //
- // Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- //
- //---------------------------------------------------------------------------------------
- //
- // To dynamically select std::filesystem where available, you could use:
- //
- // #if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
- // && __has_include(<filesystem>) #include <filesystem> namespace fs =
- // std::filesystem; #else #include <ghc/filesystem.hpp> namespace fs =
- // ghc::filesystem; #endif
- //
- //---------------------------------------------------------------------------------------
- #ifndef GHC_FILESYSTEM_H
- #define GHC_FILESYSTEM_H
- // #define BSD manifest constant only in
- // sys/param.h
- #ifndef _WIN32
- #include <sys/param.h>
- #endif
- #ifndef GHC_OS_DETECTED
- #if defined(__APPLE__) && defined(__MACH__)
- #define GHC_OS_MACOS
- #elif defined(__linux__)
- #define GHC_OS_LINUX
- #if defined(__ANDROID__)
- #define GHC_OS_ANDROID
- #endif
- #elif defined(_WIN64)
- #define GHC_OS_WINDOWS
- #define GHC_OS_WIN64
- #elif defined(_WIN32)
- #define GHC_OS_WINDOWS
- #define GHC_OS_WIN32
- #elif defined(__svr4__)
- #define GHC_OS_SYS5R4
- #elif defined(BSD)
- #define GHC_OS_BSD
- #elif defined(__EMSCRIPTEN__)
- #define GHC_OS_WEB
- #include <wasi/api.h>
- #else
- #error "Operating system currently not supported!"
- #endif
- #define GHC_OS_DETECTED
- #endif
- #if defined(GHC_FILESYSTEM_IMPLEMENTATION)
- #define GHC_EXPAND_IMPL
- #define GHC_INLINE
- #ifdef GHC_OS_WINDOWS
- #define GHC_FS_API
- #define GHC_FS_API_CLASS
- #else
- #define GHC_FS_API __attribute__((visibility("default")))
- #define GHC_FS_API_CLASS __attribute__((visibility("default")))
- #endif
- #elif defined(GHC_FILESYSTEM_FWD)
- #define GHC_INLINE
- #ifdef GHC_OS_WINDOWS
- #define GHC_FS_API extern
- #define GHC_FS_API_CLASS
- #else
- #define GHC_FS_API extern
- #define GHC_FS_API_CLASS
- #endif
- #else
- #define GHC_EXPAND_IMPL
- #define GHC_INLINE inline
- #define GHC_FS_API
- #define GHC_FS_API_CLASS
- #endif
- #ifdef GHC_EXPAND_IMPL
- #ifdef GHC_OS_WINDOWS
- #include <windows.h>
- // additional includes
- #include <shellapi.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <wchar.h>
- #include <winioctl.h>
- #else
- #include <dirent.h>
- #include <fcntl.h>
- #include <limits.h>
- #include <sys/param.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- #ifdef GHC_OS_ANDROID
- #include <android/api-level.h>
- #if __ANDROID_API__ < 12
- #include <sys/syscall.h>
- #endif
- #include <sys/vfs.h>
- #define statvfs statfs
- #else
- #include <sys/statvfs.h>
- #endif
- #if !defined(__ANDROID__) || __ANDROID_API__ >= 26
- #include <langinfo.h>
- #endif
- #endif
- #ifdef GHC_OS_MACOS
- #include <Availability.h>
- #endif
- #include <algorithm>
- #include <cctype>
- #include <chrono>
- #include <clocale>
- #include <cstdlib>
- #include <cstring>
- #include <fstream>
- #include <functional>
- #include <memory>
- #include <stack>
- #include <stdexcept>
- #include <string>
- #include <system_error>
- #include <type_traits>
- #include <utility>
- #include <vector>
- #else // GHC_EXPAND_IMPL
- #include <chrono>
- #include <fstream>
- #include <memory>
- #include <stack>
- #include <stdexcept>
- #include <string>
- #include <system_error>
- #ifdef GHC_OS_WINDOWS
- #include <vector>
- #endif
- #endif // GHC_EXPAND_IMPL
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // Behaviour Switches (see README.md, should match the config in
- // test/filesystem_test.cpp):
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // LWG #2682 disables the since then invalid use of the copy option
- // create_symlinks on directories configure LWG conformance ()
- #define LWG_2682_BEHAVIOUR
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // LWG #2395 makes crate_directory/create_directories not emit an error if there
- // is a regular file with that name, it is superceded by P1164R1, so only
- // activate if really needed #define LWG_2935_BEHAVIOUR
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // LWG #2937 enforces that fs::equivalent emits an error, if
- // !fs::exists(p1)||!exists(p2)
- #define LWG_2937_BEHAVIOUR
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // UTF8-Everywhere is the original behaviour of ghc::filesystem. With this
- // define you can enable the more standard conforming implementation option that
- // uses wstring on Windows as ghc::filesystem::string_type. #define
- // GHC_WIN_WSTRING_STRING_TYPE
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences
- // are found, instead of replacing them with the unicode replacement character
- // (U+FFFD). #define GHC_RAISE_UNICODE_ERRORS
- //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //- - - - - - - - -
- // ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
- #define GHC_FILESYSTEM_VERSION 10304L
- #if !defined(GHC_WITH_EXCEPTIONS) && \
- (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || \
- defined(_CPPUNWIND))
- #define GHC_WITH_EXCEPTIONS
- #endif
- #if !defined(GHC_WITH_EXCEPTIONS) && defined(GHC_RAISE_UNICODE_ERRORS)
- #error "Can't raise unicode errors whith exception support disabled"
- #endif
- namespace ghc { namespace filesystem {
- // temporary existing exception type for yet unimplemented parts
- class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error {
- public:
- not_implemented_exception()
- : std::logic_error("function not implemented yet.") {}
- };
- template <typename char_type> class path_helper_base {
- public:
- using value_type = char_type;
- #ifdef GHC_OS_WINDOWS
- static constexpr value_type preferred_separator = '\\';
- #else
- static constexpr value_type preferred_separator = '/';
- #endif
- };
- #if __cplusplus < 201703L
- template <typename char_type>
- constexpr char_type path_helper_base<char_type>::preferred_separator;
- #endif
- // 30.10.8 class path
- class GHC_FS_API_CLASS path
- #if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_WSTRING_STRING_TYPE)
- #define GHC_USE_WCHAR_T
- : private path_helper_base<std::wstring::value_type> {
- public:
- using path_helper_base<std::wstring::value_type>::value_type;
- #else
- : private path_helper_base<std::string::value_type> {
- public:
- using path_helper_base<std::string::value_type>::value_type;
- #endif
- using string_type = std::basic_string<value_type>;
- using path_helper_base<value_type>::preferred_separator;
- // 30.10.10.1 enumeration format
- /// The path format in wich the constructor argument is given.
- enum format {
- generic_format, ///< The generic format, internally used by
- ///< ghc::filesystem::path with slashes
- native_format, ///< The format native to the current platform this code
- ///< is build for
- auto_format, ///< Try to auto-detect the format, fallback to native
- };
- template <class T> struct _is_basic_string : std::false_type {};
- template <class CharT, class Traits, class Alloc>
- struct _is_basic_string<std::basic_string<CharT, Traits, Alloc>>
- : std::true_type {};
- #ifdef __cpp_lib_string_view
- template <class CharT>
- struct _is_basic_string<std::basic_string_view<CharT>> : std::true_type {};
- #endif
- template <typename T1, typename T2 = void>
- using path_type =
- typename std::enable_if<!std::is_same<path, T1>::value, path>::type;
- #ifdef GHC_USE_WCHAR_T
- template <typename T>
- using path_from_string = typename std::enable_if<
- _is_basic_string<T>::value ||
- std::is_same<char const *, typename std::decay<T>::type>::value ||
- std::is_same<char *, typename std::decay<T>::type>::value ||
- std::is_same<wchar_t const *,
- typename std::decay<T>::type>::value ||
- std::is_same<wchar_t *, typename std::decay<T>::type>::value,
- path>::type;
- template <typename T>
- using path_type_EcharT =
- typename std::enable_if<std::is_same<T, char>::value ||
- std::is_same<T, char16_t>::value ||
- std::is_same<T, char32_t>::value,
- path>::type;
- #else
- template <typename T>
- using path_from_string = typename std::enable_if<
- _is_basic_string<T>::value ||
- std::is_same<char const *, typename std::decay<T>::type>::value ||
- std::is_same<char *, typename std::decay<T>::type>::value,
- path>::type;
- template <typename T>
- using path_type_EcharT = typename std::enable_if<
- std::is_same<T, char>::value || std::is_same<T, char16_t>::value ||
- std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value,
- path>::type;
- #endif
- // 30.10.8.4.1 constructors and destructor
- path() noexcept;
- path(const path & p);
- path(path && p) noexcept;
- path(string_type && source, format fmt = auto_format);
- template <class Source, typename = path_from_string<Source>>
- path(const Source & source, format fmt = auto_format);
- template <class InputIterator>
- path(InputIterator first, InputIterator last, format fmt = auto_format);
- #ifdef GHC_WITH_EXCEPTIONS
- template <class Source, typename = path_from_string<Source>>
- path(const Source & source, const std::locale & loc,
- format fmt = auto_format);
- template <class InputIterator>
- path(InputIterator first, InputIterator last, const std::locale & loc,
- format fmt = auto_format);
- #endif
- ~path();
- // 30.10.8.4.2 assignments
- path & operator=(const path & p);
- path & operator=(path && p) noexcept;
- path & operator=(string_type && source);
- path & assign(string_type && source);
- template <class Source> path & operator=(const Source & source);
- template <class Source> path & assign(const Source & source);
- template <class InputIterator>
- path & assign(InputIterator first, InputIterator last);
- // 30.10.8.4.3 appends
- path & operator/=(const path & p);
- template <class Source> path & operator/=(const Source & source);
- template <class Source> path & append(const Source & source);
- template <class InputIterator>
- path & append(InputIterator first, InputIterator last);
- // 30.10.8.4.4 concatenation
- path & operator+=(const path & x);
- path & operator+=(const string_type & x);
- #ifdef __cpp_lib_string_view
- path & operator+=(std::basic_string_view<value_type> x);
- #endif
- path & operator+=(const value_type * x);
- path & operator+=(value_type x);
- template <class Source>
- path_from_string<Source> & operator+=(const Source & x);
- template <class EcharT> path_type_EcharT<EcharT> & operator+=(EcharT x);
- template <class Source> path & concat(const Source & x);
- template <class InputIterator>
- path & concat(InputIterator first, InputIterator last);
- // 30.10.8.4.5 modifiers
- void clear() noexcept;
- path & make_preferred();
- path & remove_filename();
- path & replace_filename(const path & replacement);
- path & replace_extension(const path & replacement = path());
- void swap(path & rhs) noexcept;
- // 30.10.8.4.6 native format observers
- const string_type &
- native() const; // this implementation doesn't support noexcept for native()
- const value_type *
- c_str() const; // this implementation doesn't support noexcept for c_str()
- operator string_type() const;
- template <class EcharT, class traits = std::char_traits<EcharT>,
- class Allocator = std::allocator<EcharT>>
- std::basic_string<EcharT, traits, Allocator>
- string(const Allocator & a = Allocator()) const;
- std::string string() const;
- std::wstring wstring() const;
- std::string u8string() const;
- std::u16string u16string() const;
- std::u32string u32string() const;
- // 30.10.8.4.7 generic format observers
- template <class EcharT, class traits = std::char_traits<EcharT>,
- class Allocator = std::allocator<EcharT>>
- std::basic_string<EcharT, traits, Allocator>
- generic_string(const Allocator & a = Allocator()) const;
- const std::string & generic_string()
- const; // this is different from the standard, that returns by value
- std::wstring generic_wstring() const;
- std::string generic_u8string() const;
- std::u16string generic_u16string() const;
- std::u32string generic_u32string() const;
- // 30.10.8.4.8 compare
- int compare(const path & p) const noexcept;
- int compare(const string_type & s) const;
- #ifdef __cpp_lib_string_view
- int compare(std::basic_string_view<value_type> s) const;
- #endif
- int compare(const value_type * s) const;
- // 30.10.8.4.9 decomposition
- path root_name() const;
- path root_directory() const;
- path root_path() const;
- path relative_path() const;
- path parent_path() const;
- path filename() const;
- path stem() const;
- path extension() const;
- // 30.10.8.4.10 query
- bool empty() const noexcept;
- bool has_root_name() const;
- bool has_root_directory() const;
- bool has_root_path() const;
- bool has_relative_path() const;
- bool has_parent_path() const;
- bool has_filename() const;
- bool has_stem() const;
- bool has_extension() const;
- bool is_absolute() const;
- bool is_relative() const;
- // 30.10.8.4.11 generation
- path lexically_normal() const;
- path lexically_relative(const path & base) const;
- path lexically_proximate(const path & base) const;
- // 30.10.8.5 iterators
- class iterator;
- using const_iterator = iterator;
- iterator begin() const;
- iterator end() const;
- private:
- using impl_value_type = std::string::value_type;
- using impl_string_type = std::basic_string<impl_value_type>;
- friend class directory_iterator;
- void append_name(const char * name);
- static constexpr impl_value_type generic_separator = '/';
- template <typename InputIterator> class input_iterator_range {
- public:
- typedef InputIterator iterator;
- typedef InputIterator const_iterator;
- typedef typename InputIterator::difference_type difference_type;
- input_iterator_range(const InputIterator & first,
- const InputIterator & last)
- : _first(first), _last(last) {}
- InputIterator begin() const { return _first; }
- InputIterator end() const { return _last; }
- private:
- InputIterator _first;
- InputIterator _last;
- };
- friend void swap(path & lhs, path & rhs) noexcept;
- friend size_t hash_value(const path & p) noexcept;
- static void postprocess_path_with_format(impl_string_type & p, format fmt);
- impl_string_type _path;
- #ifdef GHC_OS_WINDOWS
- impl_string_type native_impl() const;
- mutable string_type _native_cache;
- #else
- const impl_string_type & native_impl() const;
- #endif
- };
- // 30.10.8.6 path non-member functions
- GHC_FS_API void swap(path & lhs, path & rhs) noexcept;
- GHC_FS_API size_t hash_value(const path & p) noexcept;
- GHC_FS_API bool operator==(const path & lhs, const path & rhs) noexcept;
- GHC_FS_API bool operator!=(const path & lhs, const path & rhs) noexcept;
- GHC_FS_API bool operator<(const path & lhs, const path & rhs) noexcept;
- GHC_FS_API bool operator<=(const path & lhs, const path & rhs) noexcept;
- GHC_FS_API bool operator>(const path & lhs, const path & rhs) noexcept;
- GHC_FS_API bool operator>=(const path & lhs, const path & rhs) noexcept;
- GHC_FS_API path operator/(const path & lhs, const path & rhs);
- // 30.10.8.6.1 path inserter and extractor
- template <class charT, class traits>
- std::basic_ostream<charT, traits> &
- operator<<(std::basic_ostream<charT, traits> & os, const path & p);
- template <class charT, class traits>
- std::basic_istream<charT, traits> &
- operator>>(std::basic_istream<charT, traits> & is, path & p);
- // 30.10.8.6.2 path factory functions
- template <class Source, typename = path::path_from_string<Source>>
- path u8path(const Source & source);
- template <class InputIterator>
- path u8path(InputIterator first, InputIterator last);
- // 30.10.9 class filesystem_error
- class GHC_FS_API_CLASS filesystem_error : public std::system_error {
- public:
- filesystem_error(const std::string & what_arg, std::error_code ec);
- filesystem_error(const std::string & what_arg, const path & p1,
- std::error_code ec);
- filesystem_error(const std::string & what_arg, const path & p1,
- const path & p2, std::error_code ec);
- const path & path1() const noexcept;
- const path & path2() const noexcept;
- const char * what() const noexcept override;
- private:
- std::string _what_arg;
- std::error_code _ec;
- path _p1, _p2;
- };
- class GHC_FS_API_CLASS path::iterator {
- public:
- using value_type = const path;
- using difference_type = std::ptrdiff_t;
- using pointer = const path *;
- using reference = const path &;
- using iterator_category = std::bidirectional_iterator_tag;
- iterator();
- iterator(const impl_string_type::const_iterator & first,
- const impl_string_type::const_iterator & last,
- const impl_string_type::const_iterator & pos);
- iterator & operator++();
- iterator operator++(int);
- iterator & operator--();
- iterator operator--(int);
- bool operator==(const iterator & other) const;
- bool operator!=(const iterator & other) const;
- reference operator*() const;
- pointer operator->() const;
- private:
- impl_string_type::const_iterator
- increment(const std::string::const_iterator & pos) const;
- impl_string_type::const_iterator
- decrement(const std::string::const_iterator & pos) const;
- void updateCurrent();
- impl_string_type::const_iterator _first;
- impl_string_type::const_iterator _last;
- impl_string_type::const_iterator _root;
- impl_string_type::const_iterator _iter;
- path _current;
- };
- struct space_info {
- uintmax_t capacity;
- uintmax_t free;
- uintmax_t available;
- };
- // 30.10.10, enumerations
- enum class file_type {
- none,
- not_found,
- regular,
- directory,
- symlink,
- block,
- character,
- fifo,
- socket,
- unknown,
- };
- enum class perms : uint16_t {
- none = 0,
- owner_read = 0400,
- owner_write = 0200,
- owner_exec = 0100,
- owner_all = 0700,
- group_read = 040,
- group_write = 020,
- group_exec = 010,
- group_all = 070,
- others_read = 04,
- others_write = 02,
- others_exec = 01,
- others_all = 07,
- all = 0777,
- set_uid = 04000,
- set_gid = 02000,
- sticky_bit = 01000,
- mask = 07777,
- unknown = 0xffff
- };
- enum class perm_options : uint16_t {
- replace = 3,
- add = 1,
- remove = 2,
- nofollow = 4,
- };
- enum class copy_options : uint16_t {
- none = 0,
- skip_existing = 1,
- overwrite_existing = 2,
- update_existing = 4,
- recursive = 8,
- copy_symlinks = 0x10,
- skip_symlinks = 0x20,
- directories_only = 0x40,
- create_symlinks = 0x80,
- #ifndef GHC_OS_WEB
- create_hard_links = 0x100
- #endif
- };
- enum class directory_options : uint16_t {
- none = 0,
- follow_directory_symlink = 1,
- skip_permission_denied = 2,
- };
- // 30.10.11 class file_status
- class GHC_FS_API_CLASS file_status {
- public:
- // 30.10.11.1 constructors and destructor
- file_status() noexcept;
- explicit file_status(file_type ft, perms prms = perms::unknown) noexcept;
- file_status(const file_status &) noexcept;
- file_status(file_status &&) noexcept;
- ~file_status();
- // assignments:
- file_status & operator=(const file_status &) noexcept;
- file_status & operator=(file_status &&) noexcept;
- // 30.10.11.3 modifiers
- void type(file_type ft) noexcept;
- void permissions(perms prms) noexcept;
- // 30.10.11.2 observers
- file_type type() const noexcept;
- perms permissions() const noexcept;
- private:
- file_type _type;
- perms _perms;
- };
- using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
- // 30.10.12 Class directory_entry
- class GHC_FS_API_CLASS directory_entry {
- public:
- // 30.10.12.1 constructors and destructor
- directory_entry() noexcept = default;
- directory_entry(const directory_entry &) = default;
- directory_entry(directory_entry &&) noexcept = default;
- #ifdef GHC_WITH_EXCEPTIONS
- explicit directory_entry(const path & p);
- #endif
- directory_entry(const path & p, std::error_code & ec);
- ~directory_entry();
- // assignments:
- directory_entry & operator=(const directory_entry &) = default;
- directory_entry & operator=(directory_entry &&) noexcept = default;
- // 30.10.12.2 modifiers
- #ifdef GHC_WITH_EXCEPTIONS
- void assign(const path & p);
- #endif
- void assign(const path & p, std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- void replace_filename(const path & p);
- #endif
- void replace_filename(const path & p, std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- void refresh();
- #endif
- void refresh(std::error_code & ec) noexcept;
- // 30.10.12.3 observers
- const filesystem::path & path() const noexcept;
- operator const filesystem::path &() const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool exists() const;
- #endif
- bool exists(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_block_file() const;
- #endif
- bool is_block_file(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_character_file() const;
- #endif
- bool is_character_file(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_directory() const;
- #endif
- bool is_directory(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_fifo() const;
- #endif
- bool is_fifo(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_other() const;
- #endif
- bool is_other(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_regular_file() const;
- #endif
- bool is_regular_file(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_socket() const;
- #endif
- bool is_socket(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- bool is_symlink() const;
- #endif
- bool is_symlink(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- uintmax_t file_size() const;
- #endif
- uintmax_t file_size(std::error_code & ec) const noexcept;
- #ifndef GHC_OS_WEB
- #ifdef GHC_WITH_EXCEPTIONS
- uintmax_t hard_link_count() const;
- #endif
- uintmax_t hard_link_count(std::error_code & ec) const noexcept;
- #endif
- #ifdef GHC_WITH_EXCEPTIONS
- file_time_type last_write_time() const;
- #endif
- file_time_type last_write_time(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- file_status status() const;
- #endif
- file_status status(std::error_code & ec) const noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- file_status symlink_status() const;
- #endif
- file_status symlink_status(std::error_code & ec) const noexcept;
- bool operator<(const directory_entry & rhs) const noexcept;
- bool operator==(const directory_entry & rhs) const noexcept;
- bool operator!=(const directory_entry & rhs) const noexcept;
- bool operator<=(const directory_entry & rhs) const noexcept;
- bool operator>(const directory_entry & rhs) const noexcept;
- bool operator>=(const directory_entry & rhs) const noexcept;
- private:
- friend class directory_iterator;
- filesystem::path _path;
- file_status _status;
- file_status _symlink_status;
- uintmax_t _file_size = 0;
- #ifndef GHC_OS_WINDOWS
- uintmax_t _hard_link_count = 0;
- #endif
- time_t _last_write_time = 0;
- };
- // 30.10.13 Class directory_iterator
- class GHC_FS_API_CLASS directory_iterator {
- public:
- class GHC_FS_API_CLASS proxy {
- public:
- const directory_entry & operator*() const & noexcept {
- return _dir_entry;
- }
- directory_entry operator*() && noexcept { return std::move(_dir_entry); }
- private:
- explicit proxy(const directory_entry & dir_entry)
- : _dir_entry(dir_entry) {}
- friend class directory_iterator;
- friend class recursive_directory_iterator;
- directory_entry _dir_entry;
- };
- using iterator_category = std::input_iterator_tag;
- using value_type = directory_entry;
- using difference_type = std::ptrdiff_t;
- using pointer = const directory_entry *;
- using reference = const directory_entry &;
- // 30.10.13.1 member functions
- directory_iterator() noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- explicit directory_iterator(const path & p);
- directory_iterator(const path & p, directory_options options);
- #endif
- directory_iterator(const path & p, std::error_code & ec) noexcept;
- directory_iterator(const path & p, directory_options options,
- std::error_code & ec) noexcept;
- directory_iterator(const directory_iterator & rhs);
- directory_iterator(directory_iterator && rhs) noexcept;
- ~directory_iterator();
- directory_iterator & operator=(const directory_iterator & rhs);
- directory_iterator & operator=(directory_iterator && rhs) noexcept;
- const directory_entry & operator*() const;
- const directory_entry * operator->() const;
- #ifdef GHC_WITH_EXCEPTIONS
- directory_iterator & operator++();
- #endif
- directory_iterator & increment(std::error_code & ec) noexcept;
- // other members as required by 27.2.3, input iterators
- #ifdef GHC_WITH_EXCEPTIONS
- proxy operator++(int) {
- proxy p{**this};
- ++*this;
- return p;
- }
- #endif
- bool operator==(const directory_iterator & rhs) const;
- bool operator!=(const directory_iterator & rhs) const;
- private:
- friend class recursive_directory_iterator;
- class impl;
- std::shared_ptr<impl> _impl;
- };
- // 30.10.13.2 directory_iterator non-member functions
- GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept;
- GHC_FS_API directory_iterator end(const directory_iterator &) noexcept;
- // 30.10.14 class recursive_directory_iterator
- class GHC_FS_API_CLASS recursive_directory_iterator {
- public:
- using iterator_category = std::input_iterator_tag;
- using value_type = directory_entry;
- using difference_type = std::ptrdiff_t;
- using pointer = const directory_entry *;
- using reference = const directory_entry &;
- // 30.10.14.1 constructors and destructor
- recursive_directory_iterator() noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- explicit recursive_directory_iterator(const path & p);
- recursive_directory_iterator(const path & p, directory_options options);
- #endif
- recursive_directory_iterator(const path & p, directory_options options,
- std::error_code & ec) noexcept;
- recursive_directory_iterator(const path & p, std::error_code & ec) noexcept;
- recursive_directory_iterator(const recursive_directory_iterator & rhs);
- recursive_directory_iterator(recursive_directory_iterator && rhs) noexcept;
- ~recursive_directory_iterator();
- // 30.10.14.1 observers
- directory_options options() const;
- int depth() const;
- bool recursion_pending() const;
- const directory_entry & operator*() const;
- const directory_entry * operator->() const;
- // 30.10.14.1 modifiers recursive_directory_iterator&
- recursive_directory_iterator &
- operator=(const recursive_directory_iterator & rhs);
- recursive_directory_iterator &
- operator=(recursive_directory_iterator && rhs) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- recursive_directory_iterator & operator++();
- #endif
- recursive_directory_iterator & increment(std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- void pop();
- #endif
- void pop(std::error_code & ec);
- void disable_recursion_pending();
- // other members as required by 27.2.3, input iterators
- #ifdef GHC_WITH_EXCEPTIONS
- directory_iterator::proxy operator++(int) {
- directory_iterator::proxy proxy{**this};
- ++*this;
- return proxy;
- }
- #endif
- bool operator==(const recursive_directory_iterator & rhs) const;
- bool operator!=(const recursive_directory_iterator & rhs) const;
- private:
- struct recursive_directory_iterator_impl {
- directory_options _options;
- bool _recursion_pending;
- std::stack<directory_iterator> _dir_iter_stack;
- recursive_directory_iterator_impl(directory_options options,
- bool recursion_pending)
- : _options(options), _recursion_pending(recursion_pending) {}
- };
- std::shared_ptr<recursive_directory_iterator_impl> _impl;
- };
- // 30.10.14.2 directory_iterator non-member functions
- GHC_FS_API recursive_directory_iterator
- begin(recursive_directory_iterator iter) noexcept;
- GHC_FS_API recursive_directory_iterator
- end(const recursive_directory_iterator &) noexcept;
- // 30.10.15 filesystem operations
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path absolute(const path & p);
- #endif
- GHC_FS_API path absolute(const path & p, std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path canonical(const path & p);
- #endif
- GHC_FS_API path canonical(const path & p, std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void copy(const path & from, const path & to);
- #endif
- GHC_FS_API void copy(const path & from, const path & to,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void copy(const path & from, const path & to,
- copy_options options);
- #endif
- GHC_FS_API void copy(const path & from, const path & to,
- copy_options options, std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool copy_file(const path & from, const path & to);
- #endif
- GHC_FS_API bool copy_file(const path & from, const path & to,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool copy_file(const path & from, const path & to,
- copy_options option);
- #endif
- GHC_FS_API bool copy_file(const path & from, const path & to,
- copy_options option,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void copy_symlink(const path & existing_symlink,
- const path & new_symlink);
- #endif
- GHC_FS_API void copy_symlink(const path & existing_symlink,
- const path & new_symlink,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool create_directories(const path & p);
- #endif
- GHC_FS_API bool create_directories(const path & p,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool create_directory(const path & p);
- #endif
- GHC_FS_API bool create_directory(const path & p,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool create_directory(const path & p, const path & attributes);
- #endif
- GHC_FS_API bool create_directory(const path & p, const path & attributes,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void create_directory_symlink(const path & to,
- const path & new_symlink);
- #endif
- GHC_FS_API void create_directory_symlink(const path & to,
- const path & new_symlink,
- std::error_code & ec) noexcept;
- #ifndef GHC_OS_WEB
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void create_hard_link(const path & to,
- const path & new_hard_link);
- #endif
- GHC_FS_API void create_hard_link(const path & to,
- const path & new_hard_link,
- std::error_code & ec) noexcept;
- #endif
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void create_symlink(const path & to, const path & new_symlink);
- #endif
- GHC_FS_API void create_symlink(const path & to, const path & new_symlink,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path current_path();
- #endif
- GHC_FS_API path current_path(std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void current_path(const path & p);
- #endif
- GHC_FS_API void current_path(const path & p, std::error_code & ec) noexcept;
- GHC_FS_API bool exists(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool exists(const path & p);
- #endif
- GHC_FS_API bool exists(const path & p, std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool equivalent(const path & p1, const path & p2);
- #endif
- GHC_FS_API bool equivalent(const path & p1, const path & p2,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API uintmax_t file_size(const path & p);
- #endif
- GHC_FS_API uintmax_t file_size(const path & p,
- std::error_code & ec) noexcept;
- #ifndef GHC_OS_WEB
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API uintmax_t hard_link_count(const path & p);
- #endif
- GHC_FS_API uintmax_t hard_link_count(const path & p,
- std::error_code & ec) noexcept;
- #endif
- GHC_FS_API bool is_block_file(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_block_file(const path & p);
- #endif
- GHC_FS_API bool is_block_file(const path & p,
- std::error_code & ec) noexcept;
- GHC_FS_API bool is_character_file(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_character_file(const path & p);
- #endif
- GHC_FS_API bool is_character_file(const path & p,
- std::error_code & ec) noexcept;
- GHC_FS_API bool is_directory(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_directory(const path & p);
- #endif
- GHC_FS_API bool is_directory(const path & p, std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_empty(const path & p);
- #endif
- GHC_FS_API bool is_empty(const path & p, std::error_code & ec) noexcept;
- GHC_FS_API bool is_fifo(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_fifo(const path & p);
- #endif
- GHC_FS_API bool is_fifo(const path & p, std::error_code & ec) noexcept;
- GHC_FS_API bool is_other(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_other(const path & p);
- #endif
- GHC_FS_API bool is_other(const path & p, std::error_code & ec) noexcept;
- GHC_FS_API bool is_regular_file(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_regular_file(const path & p);
- #endif
- GHC_FS_API bool is_regular_file(const path & p,
- std::error_code & ec) noexcept;
- GHC_FS_API bool is_socket(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_socket(const path & p);
- #endif
- GHC_FS_API bool is_socket(const path & p, std::error_code & ec) noexcept;
- GHC_FS_API bool is_symlink(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool is_symlink(const path & p);
- #endif
- GHC_FS_API bool is_symlink(const path & p, std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API file_time_type last_write_time(const path & p);
- #endif
- GHC_FS_API file_time_type last_write_time(const path & p,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void last_write_time(const path & p, file_time_type new_time);
- #endif
- GHC_FS_API void last_write_time(const path & p, file_time_type new_time,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void permissions(const path & p, perms prms,
- perm_options opts = perm_options::replace);
- #endif
- GHC_FS_API void permissions(const path & p, perms prms,
- std::error_code & ec) noexcept;
- GHC_FS_API void permissions(const path & p, perms prms, perm_options opts,
- std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path proximate(const path & p, std::error_code & ec);
- GHC_FS_API path proximate(const path & p,
- const path & base = current_path());
- #endif
- GHC_FS_API path proximate(const path & p, const path & base,
- std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path read_symlink(const path & p);
- #endif
- GHC_FS_API path read_symlink(const path & p, std::error_code & ec);
- GHC_FS_API path relative(const path & p, std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path relative(const path & p,
- const path & base = current_path());
- #endif
- GHC_FS_API path relative(const path & p, const path & base,
- std::error_code & ec);
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API bool remove(const path & p);
- #endif
- GHC_FS_API bool remove(const path & p, std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API uintmax_t remove_all(const path & p);
- #endif
- GHC_FS_API uintmax_t remove_all(const path & p,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void rename(const path & from, const path & to);
- #endif
- GHC_FS_API void rename(const path & from, const path & to,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API void resize_file(const path & p, uintmax_t size);
- #endif
- GHC_FS_API void resize_file(const path & p, uintmax_t size,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API space_info space(const path & p);
- #endif
- GHC_FS_API space_info space(const path & p, std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API file_status status(const path & p);
- #endif
- GHC_FS_API file_status status(const path & p,
- std::error_code & ec) noexcept;
- GHC_FS_API bool status_known(file_status s) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API file_status symlink_status(const path & p);
- #endif
- GHC_FS_API file_status symlink_status(const path & p,
- std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path temp_directory_path();
- #endif
- GHC_FS_API path temp_directory_path(std::error_code & ec) noexcept;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_FS_API path weakly_canonical(const path & p);
- #endif
- GHC_FS_API path weakly_canonical(const path & p,
- std::error_code & ec) noexcept;
- // Non-C++17 add-on std::fstream wrappers with path
- template <class charT, class traits = std::char_traits<charT>>
- class basic_filebuf : public std::basic_filebuf<charT, traits> {
- public:
- basic_filebuf() {}
- ~basic_filebuf() override {}
- basic_filebuf(const basic_filebuf &) = delete;
- const basic_filebuf & operator=(const basic_filebuf &) = delete;
- basic_filebuf<charT, traits> * open(const path & p,
- std::ios_base::openmode mode) {
- #if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
- return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(),
- mode)
- ? this
- : 0;
- #else
- return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode)
- ? this
- : 0;
- #endif
- }
- };
- template <class charT, class traits = std::char_traits<charT>>
- class basic_ifstream : public std::basic_ifstream<charT, traits> {
- public:
- basic_ifstream() {}
- #if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
- explicit basic_ifstream(const path & p,
- std::ios_base::openmode mode = std::ios_base::in)
- : std::basic_ifstream<charT, traits>(p.wstring().c_str(), mode) {}
- void open(const path & p,
- std::ios_base::openmode mode = std::ios_base::in) {
- std::basic_ifstream<charT, traits>::open(p.wstring().c_str(), mode);
- }
- #else
- explicit basic_ifstream(const path & p,
- std::ios_base::openmode mode = std::ios_base::in)
- : std::basic_ifstream<charT, traits>(p.string().c_str(), mode) {}
- void open(const path & p,
- std::ios_base::openmode mode = std::ios_base::in) {
- std::basic_ifstream<charT, traits>::open(p.string().c_str(), mode);
- }
- #endif
- basic_ifstream(const basic_ifstream &) = delete;
- const basic_ifstream & operator=(const basic_ifstream &) = delete;
- ~basic_ifstream() override {}
- };
- template <class charT, class traits = std::char_traits<charT>>
- class basic_ofstream : public std::basic_ofstream<charT, traits> {
- public:
- basic_ofstream() {}
- #if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
- explicit basic_ofstream(const path & p,
- std::ios_base::openmode mode = std::ios_base::out)
- : std::basic_ofstream<charT, traits>(p.wstring().c_str(), mode) {}
- void open(const path & p,
- std::ios_base::openmode mode = std::ios_base::out) {
- std::basic_ofstream<charT, traits>::open(p.wstring().c_str(), mode);
- }
- #else
- explicit basic_ofstream(const path & p,
- std::ios_base::openmode mode = std::ios_base::out)
- : std::basic_ofstream<charT, traits>(p.string().c_str(), mode) {}
- void open(const path & p,
- std::ios_base::openmode mode = std::ios_base::out) {
- std::basic_ofstream<charT, traits>::open(p.string().c_str(), mode);
- }
- #endif
- basic_ofstream(const basic_ofstream &) = delete;
- const basic_ofstream & operator=(const basic_ofstream &) = delete;
- ~basic_ofstream() override {}
- };
- template <class charT, class traits = std::char_traits<charT>>
- class basic_fstream : public std::basic_fstream<charT, traits> {
- public:
- basic_fstream() {}
- #if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
- explicit basic_fstream(const path & p,
- std::ios_base::openmode mode = std::ios_base::in |
- std::ios_base::out)
- : std::basic_fstream<charT, traits>(p.wstring().c_str(), mode) {}
- void open(const path & p,
- std::ios_base::openmode mode = std::ios_base::in |
- std::ios_base::out) {
- std::basic_fstream<charT, traits>::open(p.wstring().c_str(), mode);
- }
- #else
- explicit basic_fstream(const path & p,
- std::ios_base::openmode mode = std::ios_base::in |
- std::ios_base::out)
- : std::basic_fstream<charT, traits>(p.string().c_str(), mode) {}
- void open(const path & p,
- std::ios_base::openmode mode = std::ios_base::in |
- std::ios_base::out) {
- std::basic_fstream<charT, traits>::open(p.string().c_str(), mode);
- }
- #endif
- basic_fstream(const basic_fstream &) = delete;
- const basic_fstream & operator=(const basic_fstream &) = delete;
- ~basic_fstream() override {}
- };
- typedef basic_filebuf<char> filebuf;
- typedef basic_filebuf<wchar_t> wfilebuf;
- typedef basic_ifstream<char> ifstream;
- typedef basic_ifstream<wchar_t> wifstream;
- typedef basic_ofstream<char> ofstream;
- typedef basic_ofstream<wchar_t> wofstream;
- typedef basic_fstream<char> fstream;
- typedef basic_fstream<wchar_t> wfstream;
- class GHC_FS_API_CLASS u8arguments {
- public:
- u8arguments(int & argc, char **& argv);
- ~u8arguments() {
- _refargc = _argc;
- _refargv = _argv;
- }
- bool valid() const { return _isvalid; }
- private:
- int _argc;
- char ** _argv;
- int & _refargc;
- char **& _refargv;
- bool _isvalid;
- #ifdef GHC_OS_WINDOWS
- std::vector<std::string> _args;
- std::vector<char *> _argp;
- #endif
- };
- //-------------------------------------------------------------------------------------------------
- // Implementation
- //-------------------------------------------------------------------------------------------------
- namespace detail {
- // GHC_FS_API void postprocess_path_with_format(path::impl_string_type& p,
- // path::format fmt);
- enum utf8_states_t { S_STRT = 0, S_RJCT = 8 };
- GHC_FS_API void appendUTF8(std::string & str, uint32_t unicode);
- GHC_FS_API bool is_surrogate(uint32_t c);
- GHC_FS_API bool is_high_surrogate(uint32_t c);
- GHC_FS_API bool is_low_surrogate(uint32_t c);
- GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state,
- const uint8_t fragment,
- uint32_t & codepoint);
- enum class portable_error {
- none = 0,
- exists,
- not_found,
- not_supported,
- not_implemented,
- invalid_argument,
- is_a_directory,
- };
- GHC_FS_API std::error_code make_error_code(portable_error err);
- #ifdef GHC_OS_WINDOWS
- GHC_FS_API std::error_code make_system_error(uint32_t err = 0);
- #else
- GHC_FS_API std::error_code make_system_error(int err = 0);
- #endif
- } // namespace detail
- namespace detail {
- #ifdef GHC_EXPAND_IMPL
- GHC_INLINE std::error_code make_error_code(portable_error err) {
- #ifdef GHC_OS_WINDOWS
- switch (err) {
- case portable_error::none:
- return std::error_code();
- case portable_error::exists:
- return std::error_code(ERROR_ALREADY_EXISTS, std::system_category());
- case portable_error::not_found:
- return std::error_code(ERROR_PATH_NOT_FOUND, std::system_category());
- case portable_error::not_supported:
- return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
- case portable_error::not_implemented:
- return std::error_code(ERROR_CALL_NOT_IMPLEMENTED,
- std::system_category());
- case portable_error::invalid_argument:
- return std::error_code(ERROR_INVALID_PARAMETER,
- std::system_category());
- case portable_error::is_a_directory:
- #ifdef ERROR_DIRECTORY_NOT_SUPPORTED
- return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED,
- std::system_category());
- #else
- return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
- #endif
- }
- #else
- switch (err) {
- case portable_error::none:
- return std::error_code();
- case portable_error::exists:
- return std::error_code(EEXIST, std::system_category());
- case portable_error::not_found:
- return std::error_code(ENOENT, std::system_category());
- case portable_error::not_supported:
- return std::error_code(ENOTSUP, std::system_category());
- case portable_error::not_implemented:
- return std::error_code(ENOSYS, std::system_category());
- case portable_error::invalid_argument:
- return std::error_code(EINVAL, std::system_category());
- case portable_error::is_a_directory:
- return std::error_code(EISDIR, std::system_category());
- }
- #endif
- return std::error_code();
- }
- #ifdef GHC_OS_WINDOWS
- GHC_INLINE std::error_code make_system_error(uint32_t err) {
- return std::error_code(err ? static_cast<int>(err)
- : static_cast<int>(::GetLastError()),
- std::system_category());
- }
- #else
- GHC_INLINE std::error_code make_system_error(int err) {
- return std::error_code(err ? err : errno, std::system_category());
- }
- #endif
- #endif // GHC_EXPAND_IMPL
- template <typename Enum>
- using EnableBitmask = typename std::enable_if<
- std::is_same<Enum, perms>::value ||
- std::is_same<Enum, perm_options>::value ||
- std::is_same<Enum, copy_options>::value ||
- std::is_same<Enum, directory_options>::value,
- Enum>::type;
- } // namespace detail
- template <typename Enum>
- detail::EnableBitmask<Enum> operator&(Enum X, Enum Y) {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(static_cast<underlying>(X) &
- static_cast<underlying>(Y));
- }
- template <typename Enum>
- detail::EnableBitmask<Enum> operator|(Enum X, Enum Y) {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(static_cast<underlying>(X) |
- static_cast<underlying>(Y));
- }
- template <typename Enum>
- detail::EnableBitmask<Enum> operator^(Enum X, Enum Y) {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(static_cast<underlying>(X) ^
- static_cast<underlying>(Y));
- }
- template <typename Enum> detail::EnableBitmask<Enum> operator~(Enum X) {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(~static_cast<underlying>(X));
- }
- template <typename Enum>
- detail::EnableBitmask<Enum> & operator&=(Enum & X, Enum Y) {
- X = X & Y;
- return X;
- }
- template <typename Enum>
- detail::EnableBitmask<Enum> & operator|=(Enum & X, Enum Y) {
- X = X | Y;
- return X;
- }
- template <typename Enum>
- detail::EnableBitmask<Enum> & operator^=(Enum & X, Enum Y) {
- X = X ^ Y;
- return X;
- }
- #ifdef GHC_EXPAND_IMPL
- namespace detail {
- GHC_INLINE bool in_range(uint32_t c, uint32_t lo, uint32_t hi) {
- return (static_cast<uint32_t>(c - lo) < (hi - lo + 1));
- }
- GHC_INLINE bool is_surrogate(uint32_t c) {
- return in_range(c, 0xd800, 0xdfff);
- }
- GHC_INLINE bool is_high_surrogate(uint32_t c) {
- return (c & 0xfffffc00) == 0xd800;
- }
- GHC_INLINE bool is_low_surrogate(uint32_t c) {
- return (c & 0xfffffc00) == 0xdc00;
- }
- GHC_INLINE void appendUTF8(std::string & str, uint32_t unicode) {
- if (unicode <= 0x7f) {
- str.push_back(static_cast<char>(unicode));
- } else if (unicode >= 0x80 && unicode <= 0x7ff) {
- str.push_back(static_cast<char>((unicode >> 6) + 192));
- str.push_back(static_cast<char>((unicode & 0x3f) + 128));
- } else if ((unicode >= 0x800 && unicode <= 0xd7ff) ||
- (unicode >= 0xe000 && unicode <= 0xffff)) {
- str.push_back(static_cast<char>((unicode >> 12) + 224));
- str.push_back(static_cast<char>(((unicode & 0xfff) >> 6) + 128));
- str.push_back(static_cast<char>((unicode & 0x3f) + 128));
- } else if (unicode >= 0x10000 && unicode <= 0x10ffff) {
- str.push_back(static_cast<char>((unicode >> 18) + 240));
- str.push_back(static_cast<char>(((unicode & 0x3ffff) >> 12) + 128));
- str.push_back(static_cast<char>(((unicode & 0xfff) >> 6) + 128));
- str.push_back(static_cast<char>((unicode & 0x3f) + 128));
- } else {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- throw filesystem_error(
- "Illegal code point for unicode character.", str,
- std::make_error_code(std::errc::illegal_byte_sequence));
- #else
- appendUTF8(str, 0xfffd);
- #endif
- }
- }
- // Thanks to Bjoern Hoehrmann
- // (https://bjoern.hoehrmann.de/utf-8/decoder/dfa/) and Taylor R Campbell
- // for the ideas to this DFA approach of UTF-8 decoding; Generating
- // debugging and shrinking my own DFA from scratch was a day of fun!
- GHC_INLINE unsigned consumeUtf8Fragment(const unsigned state,
- const uint8_t fragment,
- uint32_t & codepoint) {
- static const uint32_t utf8_state_info[] = {
- // encoded states
- 0x11111111u, 0x11111111u, 0x77777777u, 0x77777777u, 0x88888888u,
- 0x88888888u, 0x88888888u, 0x88888888u, 0x22222299u, 0x22222222u,
- 0x22222222u, 0x22222222u, 0x3333333au, 0x33433333u, 0x9995666bu,
- 0x99999999u, 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u,
- 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u,
- 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u,
- 0u, 0u,
- };
- uint8_t category = fragment < 128
- ? 0
- : (utf8_state_info[(fragment >> 3) & 0xf] >>
- ((fragment & 7) << 2)) &
- 0xf;
- codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu)
- : (0xffu >> category) & fragment);
- return state == S_RJCT
- ? static_cast<unsigned>(S_RJCT)
- : static_cast<unsigned>(
- (utf8_state_info[category + 16] >> (state << 2)) &
- 0xf);
- }
- GHC_INLINE bool validUtf8(const std::string & utf8String) {
- std::string::const_iterator iter = utf8String.begin();
- unsigned utf8_state = S_STRT;
- std::uint32_t codepoint = 0;
- while (iter < utf8String.end()) {
- if ((utf8_state = consumeUtf8Fragment(utf8_state,
- static_cast<uint8_t>(*iter++),
- codepoint)) == S_RJCT) {
- return false;
- }
- }
- if (utf8_state) { return false; }
- return true;
- }
- } // namespace detail
- #endif
- namespace detail {
- template <class StringType, typename std::enable_if<(
- sizeof(typename StringType::value_type) ==
- 1)>::type * = nullptr>
- inline StringType
- fromUtf8(const std::string & utf8String,
- const typename StringType::allocator_type & alloc =
- typename StringType::allocator_type()) {
- return StringType(utf8String.begin(), utf8String.end(), alloc);
- }
- template <class StringType, typename std::enable_if<(
- sizeof(typename StringType::value_type) ==
- 2)>::type * = nullptr>
- inline StringType
- fromUtf8(const std::string & utf8String,
- const typename StringType::allocator_type & alloc =
- typename StringType::allocator_type()) {
- StringType result(alloc);
- result.reserve(utf8String.length());
- std::string::const_iterator iter = utf8String.begin();
- unsigned utf8_state = S_STRT;
- std::uint32_t codepoint = 0;
- while (iter < utf8String.end()) {
- if ((utf8_state = consumeUtf8Fragment(utf8_state,
- static_cast<uint8_t>(*iter++),
- codepoint)) == S_STRT) {
- if (codepoint <= 0xffff) {
- result += static_cast<typename StringType::value_type>(codepoint);
- } else {
- codepoint -= 0x10000;
- result += static_cast<typename StringType::value_type>(
- (codepoint >> 10) + 0xd800);
- result += static_cast<typename StringType::value_type>(
- (codepoint & 0x3ff) + 0xdc00);
- }
- codepoint = 0;
- } else if (utf8_state == S_RJCT) {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- throw filesystem_error(
- "Illegal byte sequence for unicode character.", utf8String,
- std::make_error_code(std::errc::illegal_byte_sequence));
- #else
- result += static_cast<typename StringType::value_type>(0xfffd);
- utf8_state = S_STRT;
- codepoint = 0;
- #endif
- }
- }
- if (utf8_state) {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- throw filesystem_error(
- "Illegal byte sequence for unicode character.", utf8String,
- std::make_error_code(std::errc::illegal_byte_sequence));
- #else
- result += static_cast<typename StringType::value_type>(0xfffd);
- #endif
- }
- return result;
- }
- template <class StringType, typename std::enable_if<(
- sizeof(typename StringType::value_type) ==
- 4)>::type * = nullptr>
- inline StringType
- fromUtf8(const std::string & utf8String,
- const typename StringType::allocator_type & alloc =
- typename StringType::allocator_type()) {
- StringType result(alloc);
- result.reserve(utf8String.length());
- std::string::const_iterator iter = utf8String.begin();
- unsigned utf8_state = S_STRT;
- std::uint32_t codepoint = 0;
- while (iter < utf8String.end()) {
- if ((utf8_state = consumeUtf8Fragment(utf8_state,
- static_cast<uint8_t>(*iter++),
- codepoint)) == S_STRT) {
- result += static_cast<typename StringType::value_type>(codepoint);
- codepoint = 0;
- } else if (utf8_state == S_RJCT) {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- throw filesystem_error(
- "Illegal byte sequence for unicode character.", utf8String,
- std::make_error_code(std::errc::illegal_byte_sequence));
- #else
- result += static_cast<typename StringType::value_type>(0xfffd);
- utf8_state = S_STRT;
- codepoint = 0;
- #endif
- }
- }
- if (utf8_state) {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- throw filesystem_error(
- "Illegal byte sequence for unicode character.", utf8String,
- std::make_error_code(std::errc::illegal_byte_sequence));
- #else
- result += static_cast<typename StringType::value_type>(0xfffd);
- #endif
- }
- return result;
- }
- template <
- typename charT, typename traits, typename Alloc,
- typename std::enable_if<(sizeof(charT) == 1), int>::type size = 1>
- inline std::string
- toUtf8(const std::basic_string<charT, traits, Alloc> & unicodeString) {
- return std::string(unicodeString.begin(), unicodeString.end());
- }
- template <
- typename charT, typename traits, typename Alloc,
- typename std::enable_if<(sizeof(charT) == 2), int>::type size = 2>
- inline std::string
- toUtf8(const std::basic_string<charT, traits, Alloc> & unicodeString) {
- std::string result;
- for (auto iter = unicodeString.begin(); iter != unicodeString.end();
- ++iter) {
- char32_t c = *iter;
- if (is_surrogate(c)) {
- ++iter;
- if (iter != unicodeString.end() && is_high_surrogate(c) &&
- is_low_surrogate(*iter)) {
- appendUTF8(result, (char32_t(c) << 10) + *iter - 0x35fdc00);
- } else {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- throw filesystem_error(
- "Illegal code point for unicode character.", result,
- std::make_error_code(std::errc::illegal_byte_sequence));
- #else
- appendUTF8(result, 0xfffd);
- if (iter == unicodeString.end()) { break; }
- #endif
- }
- } else {
- appendUTF8(result, c);
- }
- }
- return result;
- }
- template <
- typename charT, typename traits, typename Alloc,
- typename std::enable_if<(sizeof(charT) == 4), int>::type size = 4>
- inline std::string
- toUtf8(const std::basic_string<charT, traits, Alloc> & unicodeString) {
- std::string result;
- for (auto c : unicodeString) {
- appendUTF8(result, static_cast<uint32_t>(c));
- }
- return result;
- }
- template <typename charT>
- inline std::string toUtf8(const charT * unicodeString) {
- return toUtf8(
- std::basic_string<charT, std::char_traits<charT>>(unicodeString));
- }
- } // namespace detail
- #ifdef GHC_EXPAND_IMPL
- namespace detail {
- GHC_INLINE bool startsWith(const std::string & what,
- const std::string & with) {
- return with.length() <= what.length() &&
- equal(with.begin(), with.end(), what.begin());
- }
- } // namespace detail
- GHC_INLINE void
- path::postprocess_path_with_format(path::impl_string_type & p,
- path::format fmt) {
- #ifdef GHC_RAISE_UNICODE_ERRORS
- if (!detail::validUtf8(p)) {
- path t;
- t._path = p;
- throw filesystem_error(
- "Illegal byte sequence for unicode character.", t,
- std::make_error_code(std::errc::illegal_byte_sequence));
- }
- #endif
- switch (fmt) {
- #ifndef GHC_OS_WINDOWS
- case path::auto_format:
- case path::native_format:
- #endif
- case path::generic_format:
- // nothing to do
- break;
- #ifdef GHC_OS_WINDOWS
- case path::auto_format:
- case path::native_format:
- if (detail::startsWith(p, std::string("\\\\?\\"))) {
- // remove Windows long filename marker
- p.erase(0, 4);
- if (detail::startsWith(p, std::string("UNC\\"))) {
- p.erase(0, 2);
- p[0] = '\\';
- }
- }
- for (auto & c : p) {
- if (c == '\\') { c = '/'; }
- }
- break;
- #endif
- }
- if (p.length() > 2 && p[0] == '/' && p[1] == '/' && p[2] != '/') {
- std::string::iterator new_end =
- std::unique(p.begin() + 2, p.end(),
- [](path::value_type lhs, path::value_type rhs) {
- return lhs == rhs && lhs == '/';
- });
- p.erase(new_end, p.end());
- } else {
- std::string::iterator new_end = std::unique(
- p.begin(), p.end(), [](path::value_type lhs, path::value_type rhs) {
- return lhs == rhs && lhs == '/';
- });
- p.erase(new_end, p.end());
- }
- }
- #endif // GHC_EXPAND_IMPL
- template <class Source, typename>
- inline path::path(const Source & source, format fmt)
- : _path(detail::toUtf8(source)) {
- postprocess_path_with_format(_path, fmt);
- }
- template <> inline path::path(const std::wstring & source, format fmt) {
- _path = detail::toUtf8(source);
- postprocess_path_with_format(_path, fmt);
- }
- template <> inline path::path(const std::u16string & source, format fmt) {
- _path = detail::toUtf8(source);
- postprocess_path_with_format(_path, fmt);
- }
- template <> inline path::path(const std::u32string & source, format fmt) {
- _path = detail::toUtf8(source);
- postprocess_path_with_format(_path, fmt);
- }
- #ifdef __cpp_lib_string_view
- template <> inline path::path(const std::string_view & source, format fmt) {
- _path = detail::toUtf8(std::string(source));
- postprocess_path_with_format(_path, fmt);
- }
- #ifdef GHC_USE_WCHAR_T
- template <>
- inline path::path(const std::wstring_view & source, format fmt) {
- _path = detail::toUtf8(std::wstring(source).c_str());
- postprocess_path_with_format(_path, fmt);
- }
- #endif
- #endif
- template <class Source, typename>
- inline path u8path(const Source & source) {
- return path(source);
- }
- template <class InputIterator>
- inline path u8path(InputIterator first, InputIterator last) {
- return path(first, last);
- }
- template <class InputIterator>
- inline path::path(InputIterator first, InputIterator last, format fmt)
- : path(std::basic_string<
- typename std::iterator_traits<InputIterator>::value_type>(
- first, last),
- fmt) {
- // delegated
- }
- #ifdef GHC_EXPAND_IMPL
- namespace detail {
- GHC_INLINE bool equals_simple_insensitive(const char * str1,
- const char * str2) {
- #ifdef GHC_OS_WINDOWS
- #ifdef __GNUC__
- while (::tolower((unsigned char)*str1) ==
- ::tolower((unsigned char)*str2++)) {
- if (*str1++ == 0) return true;
- }
- return false;
- #else
- return 0 == ::_stricmp(str1, str2);
- #endif
- #else
- return 0 == ::strcasecmp(str1, str2);
- #endif
- }
- GHC_INLINE const char * strerror_adapter(char * gnu, char *) {
- return gnu;
- }
- GHC_INLINE const char * strerror_adapter(int posix, char * buffer) {
- if (posix) { return "Error in strerror_r!"; }
- return buffer;
- }
- template <typename ErrorNumber>
- GHC_INLINE std::string systemErrorText(ErrorNumber code = 0) {
- #if defined(GHC_OS_WINDOWS)
- LPVOID msgBuf;
- DWORD dw = code ? static_cast<DWORD>(code) : ::GetLastError();
- FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPWSTR)&msgBuf, 0, NULL);
- std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf));
- LocalFree(msgBuf);
- return msg;
- #else
- char buffer[512];
- return strerror_adapter(
- strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer);
- #endif
- }
- #ifdef GHC_OS_WINDOWS
- using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI *)(LPCWSTR, LPCWSTR, DWORD);
- using CreateHardLinkW_fp = BOOLEAN(WINAPI *)(LPCWSTR, LPCWSTR,
- LPSECURITY_ATTRIBUTES);
- GHC_INLINE void create_symlink(const path & target_name,
- const path & new_symlink,
- bool to_directory, std::error_code & ec) {
- std::error_code tec;
- auto fs = status(target_name, tec);
- if ((fs.type() == file_type::directory && !to_directory) ||
- (fs.type() == file_type::regular && to_directory)) {
- ec = detail::make_error_code(detail::portable_error::not_supported);
- return;
- }
- #if defined(__GNUC__) && __GNUC__ >= 8
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wcast-function-type"
- #endif
- static CreateSymbolicLinkW_fp api_call =
- reinterpret_cast<CreateSymbolicLinkW_fp>(GetProcAddress(
- GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
- #if defined(__GNUC__) && __GNUC__ >= 8
- #pragma GCC diagnostic pop
- #endif
- if (api_call) {
- if (api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string())
- .c_str(),
- detail::fromUtf8<std::wstring>(target_name.u8string())
- .c_str(),
- to_directory ? 1 : 0) == 0) {
- auto result = ::GetLastError();
- if (result == ERROR_PRIVILEGE_NOT_HELD &&
- api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string())
- .c_str(),
- detail::fromUtf8<std::wstring>(target_name.u8string())
- .c_str(),
- to_directory ? 3 : 2) != 0) {
- return;
- }
- ec = detail::make_system_error(result);
- }
- } else {
- ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
- }
- }
- GHC_INLINE void create_hardlink(const path & target_name,
- const path & new_hardlink,
- std::error_code & ec) {
- #if defined(__GNUC__) && __GNUC__ >= 8
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wcast-function-type"
- #endif
- static CreateHardLinkW_fp api_call =
- reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(
- GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
- #if defined(__GNUC__) && __GNUC__ >= 8
- #pragma GCC diagnostic pop
- #endif
- if (api_call) {
- if (api_call(detail::fromUtf8<std::wstring>(new_hardlink.u8string())
- .c_str(),
- detail::fromUtf8<std::wstring>(target_name.u8string())
- .c_str(),
- NULL) == 0) {
- ec = detail::make_system_error();
- }
- } else {
- ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
- }
- }
- #else
- GHC_INLINE void create_symlink(const path & target_name,
- const path & new_symlink, bool,
- std::error_code & ec) {
- if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) {
- ec = detail::make_system_error();
- }
- }
- #ifndef GHC_OS_WEB
- GHC_INLINE void create_hardlink(const path & target_name,
- const path & new_hardlink,
- std::error_code & ec) {
- if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
- ec = detail::make_system_error();
- }
- }
- #endif
- #endif
- template <typename T>
- GHC_INLINE file_status file_status_from_st_mode(T mode) {
- #ifdef GHC_OS_WINDOWS
- file_type ft = file_type::unknown;
- if ((mode & _S_IFDIR) == _S_IFDIR) {
- ft = file_type::directory;
- } else if ((mode & _S_IFREG) == _S_IFREG) {
- ft = file_type::regular;
- } else if ((mode & _S_IFCHR) == _S_IFCHR) {
- ft = file_type::character;
- }
- perms prms = static_cast<perms>(mode & 0xfff);
- return file_status(ft, prms);
- #else
- file_type ft = file_type::unknown;
- if (S_ISDIR(mode)) {
- ft = file_type::directory;
- } else if (S_ISREG(mode)) {
- ft = file_type::regular;
- } else if (S_ISCHR(mode)) {
- ft = file_type::character;
- } else if (S_ISBLK(mode)) {
- ft = file_type::block;
- } else if (S_ISFIFO(mode)) {
- ft = file_type::fifo;
- } else if (S_ISLNK(mode)) {
- ft = file_type::symlink;
- } else if (S_ISSOCK(mode)) {
- ft = file_type::socket;
- }
- perms prms = static_cast<perms>(mode & 0xfff);
- return file_status(ft, prms);
- #endif
- }
- GHC_INLINE path resolveSymlink(const path & p, std::error_code & ec) {
- #ifdef GHC_OS_WINDOWS
- #ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
- typedef struct _REPARSE_DATA_BUFFER {
- ULONG ReparseTag;
- USHORT ReparseDataLength;
- USHORT Reserved;
- union {
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- ULONG Flags;
- WCHAR PathBuffer[1];
- } SymbolicLinkReparseBuffer;
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- WCHAR PathBuffer[1];
- } MountPointReparseBuffer;
- struct {
- UCHAR DataBuffer[1];
- } GenericReparseBuffer;
- } DUMMYUNIONNAME;
- } REPARSE_DATA_BUFFER;
- #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
- #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
- #endif
- #endif
- std::shared_ptr<void> file(
- CreateFileW(
- p.wstring().c_str(), 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
- OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0),
- CloseHandle);
- if (file.get() == INVALID_HANDLE_VALUE) {
- ec = detail::make_system_error();
- return path();
- }
- std::shared_ptr<REPARSE_DATA_BUFFER> reparseData(
- (REPARSE_DATA_BUFFER *)std::calloc(
- 1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE),
- std::free);
- ULONG bufferUsed;
- path result;
- if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0,
- reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
- &bufferUsed, 0)) {
- if (IsReparseTagMicrosoft(reparseData->ReparseTag)) {
- switch (reparseData->ReparseTag) {
- case IO_REPARSE_TAG_SYMLINK:
- result = std::wstring(
- &reparseData->SymbolicLinkReparseBuffer.PathBuffer
- [reparseData->SymbolicLinkReparseBuffer.PrintNameOffset /
- sizeof(WCHAR)],
- reparseData->SymbolicLinkReparseBuffer.PrintNameLength /
- sizeof(WCHAR));
- break;
- case IO_REPARSE_TAG_MOUNT_POINT:
- result = std::wstring(
- &reparseData->MountPointReparseBuffer.PathBuffer
- [reparseData->MountPointReparseBuffer.PrintNameOffset /
- sizeof(WCHAR)],
- reparseData->MountPointReparseBuffer.PrintNameLength /
- sizeof(WCHAR));
- break;
- default:
- break;
- }
- }
- } else {
- ec = detail::make_system_error();
- }
- return result;
- #else
- size_t bufferSize = 256;
- while (true) {
- std::vector<char> buffer(bufferSize, static_cast<char>(0));
- auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size());
- if (rc < 0) {
- ec = detail::make_system_error();
- return path();
- } else if (rc < static_cast<int>(bufferSize)) {
- return path(std::string(buffer.data(),
- static_cast<std::string::size_type>(rc)));
- }
- bufferSize *= 2;
- }
- return path();
- #endif
- }
- #ifdef GHC_OS_WINDOWS
- GHC_INLINE time_t timeFromFILETIME(const FILETIME & ft) {
- ULARGE_INTEGER ull;
- ull.LowPart = ft.dwLowDateTime;
- ull.HighPart = ft.dwHighDateTime;
- return static_cast<time_t>(ull.QuadPart / 10000000ULL - 11644473600ULL);
- }
- GHC_INLINE void timeToFILETIME(time_t t, FILETIME & ft) {
- LONGLONG ll;
- ll = Int32x32To64(t, 10000000) + 116444736000000000;
- ft.dwLowDateTime = static_cast<DWORD>(ll);
- ft.dwHighDateTime = static_cast<DWORD>(ll >> 32);
- }
- template <typename INFO>
- GHC_INLINE uintmax_t hard_links_from_INFO(const INFO * info) {
- return static_cast<uintmax_t>(-1);
- }
- template <>
- GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(
- const BY_HANDLE_FILE_INFORMATION * info) {
- return info->nNumberOfLinks;
- }
- template <typename INFO>
- GHC_INLINE file_status status_from_INFO(const path & p, const INFO * info,
- std::error_code &,
- uintmax_t * sz = nullptr,
- time_t * lwt = nullptr) noexcept {
- file_type ft = file_type::unknown;
- if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
- ft = file_type::symlink;
- } else {
- if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- ft = file_type::directory;
- } else {
- ft = file_type::regular;
- }
- }
- perms prms = perms::owner_read | perms::group_read | perms::others_read;
- if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
- prms = prms | perms::owner_write | perms::group_write |
- perms::others_write;
- }
- std::string ext = p.extension().generic_string();
- if (equals_simple_insensitive(ext.c_str(), ".exe") ||
- equals_simple_insensitive(ext.c_str(), ".cmd") ||
- equals_simple_insensitive(ext.c_str(), ".bat") ||
- equals_simple_insensitive(ext.c_str(), ".com")) {
- prms =
- prms | perms::owner_exec | perms::group_exec | perms::others_exec;
- }
- if (sz) {
- *sz = static_cast<uintmax_t>(info->nFileSizeHigh)
- << (sizeof(info->nFileSizeHigh) * 8) |
- info->nFileSizeLow;
- }
- if (lwt) { *lwt = detail::timeFromFILETIME(info->ftLastWriteTime); }
- return file_status(ft, prms);
- }
- #endif
- GHC_INLINE bool is_not_found_error(std::error_code & ec) {
- #ifdef GHC_OS_WINDOWS
- return ec.value() == ERROR_FILE_NOT_FOUND ||
- ec.value() == ERROR_PATH_NOT_FOUND ||
- ec.value() == ERROR_INVALID_NAME;
- #else
- return ec.value() == ENOENT || ec.value() == ENOTDIR;
- #endif
- }
- GHC_INLINE file_status symlink_status_ex(
- const path & p, std::error_code & ec, uintmax_t * sz = nullptr,
- uintmax_t * nhl = nullptr, time_t * lwt = nullptr) noexcept {
- #ifdef GHC_OS_WINDOWS
- file_status fs;
- WIN32_FILE_ATTRIBUTE_DATA attr;
- if (!GetFileAttributesExW(
- detail::fromUtf8<std::wstring>(p.u8string()).c_str(),
- GetFileExInfoStandard, &attr)) {
- ec = detail::make_system_error();
- } else {
- ec.clear();
- fs = detail::status_from_INFO(p, &attr, ec, sz, lwt);
- if (nhl) { *nhl = 0; }
- if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- fs.type(file_type::symlink);
- }
- }
- if (detail::is_not_found_error(ec)) {
- return file_status(file_type::not_found);
- }
- return ec ? file_status(file_type::none) : fs;
- #else
- (void)sz;
- (void)nhl;
- (void)lwt;
- struct ::stat fs;
- auto result = ::lstat(p.c_str(), &fs);
- if (result == 0) {
- ec.clear();
- file_status f_s = detail::file_status_from_st_mode(fs.st_mode);
- return f_s;
- }
- ec = detail::make_system_error();
- if (detail::is_not_found_error(ec)) {
- return file_status(file_type::not_found, perms::unknown);
- }
- return file_status(file_type::none);
- #endif
- }
- GHC_INLINE file_status status_ex(const path & p, std::error_code & ec,
- file_status * sls = nullptr,
- uintmax_t * sz = nullptr,
- uintmax_t * nhl = nullptr,
- time_t * lwt = nullptr,
- int recurse_count = 0) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- if (recurse_count > 16) {
- ec = detail::make_system_error(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/);
- return file_status(file_type::unknown);
- }
- WIN32_FILE_ATTRIBUTE_DATA attr;
- if (!::GetFileAttributesExW(p.wstring().c_str(), GetFileExInfoStandard,
- &attr)) {
- ec = detail::make_system_error();
- } else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- path target = resolveSymlink(p, ec);
- file_status result;
- if (!ec && !target.empty()) {
- if (sls) { *sls = status_from_INFO(p, &attr, ec); }
- return detail::status_ex(target, ec, nullptr, sz, nhl, lwt,
- recurse_count + 1);
- }
- return file_status(file_type::unknown);
- }
- if (ec) {
- if (detail::is_not_found_error(ec)) {
- return file_status(file_type::not_found);
- }
- return file_status(file_type::none);
- }
- if (nhl) { *nhl = 0; }
- return detail::status_from_INFO(p, &attr, ec, sz, lwt);
- #else
- (void)recurse_count;
- struct ::stat st;
- auto result = ::lstat(p.c_str(), &st);
- if (result == 0) {
- ec.clear();
- file_status fs = detail::file_status_from_st_mode(st.st_mode);
- if (fs.type() == file_type::symlink) {
- result = ::stat(p.c_str(), &st);
- if (result == 0) {
- if (sls) { *sls = fs; }
- fs = detail::file_status_from_st_mode(st.st_mode);
- }
- }
- if (sz) { *sz = static_cast<uintmax_t>(st.st_size); }
- if (nhl) { *nhl = st.st_nlink; }
- if (lwt) { *lwt = st.st_mtime; }
- return fs;
- } else {
- ec = detail::make_system_error();
- if (detail::is_not_found_error(ec)) {
- return file_status(file_type::not_found, perms::unknown);
- }
- return file_status(file_type::none);
- }
- #endif
- }
- } // namespace detail
- GHC_INLINE u8arguments::u8arguments(int & argc, char **& argv)
- : _argc(argc), _argv(argv), _refargc(argc), _refargv(argv),
- _isvalid(false) {
- #ifdef GHC_OS_WINDOWS
- LPWSTR * p;
- p = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
- _args.reserve(static_cast<size_t>(argc));
- _argp.reserve(static_cast<size_t>(argc));
- for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
- _args.push_back(detail::toUtf8(std::wstring(p[i])));
- _argp.push_back((char *)_args[i].data());
- }
- argv = _argp.data();
- ::LocalFree(p);
- _isvalid = true;
- #else
- std::setlocale(LC_ALL, "");
- #if defined(__ANDROID__) && __ANDROID_API__ < 26
- _isvalid = true;
- #else
- if (detail::equals_simple_insensitive(::nl_langinfo(CODESET), "UTF-8")) {
- _isvalid = true;
- }
- #endif
- #endif
- }
- //-----------------------------------------------------------------------------
- // 30.10.8.4.1 constructors and destructor
- GHC_INLINE path::path() noexcept {}
- GHC_INLINE path::path(const path & p) : _path(p._path) {}
- GHC_INLINE path::path(path && p) noexcept : _path(std::move(p._path)) {}
- GHC_INLINE path::path(string_type && source, format fmt)
- #ifdef GHC_USE_WCHAR_T
- : _path(detail::toUtf8(source))
- #else
- : _path(std::move(source))
- #endif
- {
- postprocess_path_with_format(_path, fmt);
- }
- #endif // GHC_EXPAND_IMPL
- #ifdef GHC_WITH_EXCEPTIONS
- template <class Source, typename>
- inline path::path(const Source & source, const std::locale & loc,
- format fmt)
- : path(source, fmt) {
- std::string locName = loc.name();
- if (!(locName.length() >= 5 &&
- (locName.substr(locName.length() - 5) == "UTF-8" ||
- locName.substr(locName.length() - 5) == "utf-8"))) {
- throw filesystem_error(
- "This implementation only supports UTF-8 locales!", path(_path),
- detail::make_error_code(detail::portable_error::not_supported));
- }
- }
- template <class InputIterator>
- inline path::path(InputIterator first, InputIterator last,
- const std::locale & loc, format fmt)
- : path(std::basic_string<
- typename std::iterator_traits<InputIterator>::value_type>(
- first, last),
- fmt) {
- std::string locName = loc.name();
- if (!(locName.length() >= 5 &&
- (locName.substr(locName.length() - 5) == "UTF-8" ||
- locName.substr(locName.length() - 5) == "utf-8"))) {
- throw filesystem_error(
- "This implementation only supports UTF-8 locales!", path(_path),
- detail::make_error_code(detail::portable_error::not_supported));
- }
- }
- #endif
- #ifdef GHC_EXPAND_IMPL
- GHC_INLINE path::~path() {}
- //-----------------------------------------------------------------------------
- // 30.10.8.4.2 assignments
- GHC_INLINE path & path::operator=(const path & p) {
- _path = p._path;
- return *this;
- }
- GHC_INLINE path & path::operator=(path && p) noexcept {
- _path = std::move(p._path);
- return *this;
- }
- GHC_INLINE path & path::operator=(path::string_type && source) {
- return assign(source);
- }
- GHC_INLINE path & path::assign(path::string_type && source) {
- #ifdef GHC_USE_WCHAR_T
- _path = detail::toUtf8(source);
- #else
- _path = std::move(source);
- #endif
- postprocess_path_with_format(_path, native_format);
- return *this;
- }
- #endif // GHC_EXPAND_IMPL
- template <class Source>
- inline path & path::operator=(const Source & source) {
- return assign(source);
- }
- template <class Source> inline path & path::assign(const Source & source) {
- _path.assign(detail::toUtf8(source));
- postprocess_path_with_format(_path, native_format);
- return *this;
- }
- template <> inline path & path::assign<path>(const path & source) {
- _path = source._path;
- return *this;
- }
- template <class InputIterator>
- inline path & path::assign(InputIterator first, InputIterator last) {
- _path.assign(first, last);
- postprocess_path_with_format(_path, native_format);
- return *this;
- }
- #ifdef GHC_EXPAND_IMPL
- //-----------------------------------------------------------------------------
- // 30.10.8.4.3 appends
- GHC_INLINE path & path::operator/=(const path & p) {
- if (p.empty()) {
- // was: if ((!has_root_directory() && is_absolute()) || has_filename())
- if (!_path.empty() && _path[_path.length() - 1] != '/' &&
- _path[_path.length() - 1] != ':') {
- _path += '/';
- }
- return *this;
- }
- if ((p.is_absolute() && (_path != root_name() || p._path != "/")) ||
- (p.has_root_name() && p.root_name() != root_name())) {
- assign(p);
- return *this;
- }
- if (p.has_root_directory()) {
- assign(root_name());
- } else if ((!has_root_directory() && is_absolute()) || has_filename()) {
- _path += '/';
- }
- auto iter = p.begin();
- bool first = true;
- if (p.has_root_name()) { ++iter; }
- while (iter != p.end()) {
- if (!first && !(!_path.empty() && _path[_path.length() - 1] == '/')) {
- _path += '/';
- }
- first = false;
- _path += (*iter++).generic_string();
- }
- return *this;
- }
- GHC_INLINE void path::append_name(const char * name) {
- if (_path.empty()) {
- this->operator/=(path(name));
- } else {
- if (_path.back() != path::generic_separator) {
- _path.push_back(path::generic_separator);
- }
- _path += name;
- }
- }
- #endif // GHC_EXPAND_IMPL
- template <class Source>
- inline path & path::operator/=(const Source & source) {
- return append(source);
- }
- template <class Source> inline path & path::append(const Source & source) {
- return this->operator/=(path(detail::toUtf8(source)));
- }
- template <> inline path & path::append<path>(const path & p) {
- return this->operator/=(p);
- }
- template <class InputIterator>
- inline path & path::append(InputIterator first, InputIterator last) {
- std::basic_string<
- typename std::iterator_traits<InputIterator>::value_type>
- part(first, last);
- return append(part);
- }
- #ifdef GHC_EXPAND_IMPL
- //-----------------------------------------------------------------------------
- // 30.10.8.4.4 concatenation
- GHC_INLINE path & path::operator+=(const path & x) {
- return concat(x._path);
- }
- GHC_INLINE path & path::operator+=(const string_type & x) {
- return concat(x);
- }
- #ifdef __cpp_lib_string_view
- GHC_INLINE path & path::operator+=(std::basic_string_view<value_type> x) {
- return concat(x);
- }
- #endif
- GHC_INLINE path & path::operator+=(const value_type * x) {
- return concat(string_type(x));
- }
- GHC_INLINE path & path::operator+=(value_type x) {
- #ifdef GHC_OS_WINDOWS
- if (x == '\\') { x = generic_separator; }
- #endif
- if (_path.empty() || _path.back() != generic_separator) {
- #ifdef GHC_USE_WCHAR_T
- _path += detail::toUtf8(string_type(1, x));
- #else
- _path += x;
- #endif
- }
- return *this;
- }
- #endif // GHC_EXPAND_IMPL
- template <class Source>
- inline path::path_from_string<Source> & path::operator+=(const Source & x) {
- return concat(x);
- }
- template <class EcharT>
- inline path::path_type_EcharT<EcharT> & path::operator+=(EcharT x) {
- std::basic_string<EcharT> part(1, x);
- concat(detail::toUtf8(part));
- return *this;
- }
- template <class Source> inline path & path::concat(const Source & x) {
- path p(x);
- postprocess_path_with_format(p._path, native_format);
- _path += p._path;
- return *this;
- }
- template <class InputIterator>
- inline path & path::concat(InputIterator first, InputIterator last) {
- _path.append(first, last);
- postprocess_path_with_format(_path, native_format);
- return *this;
- }
- #ifdef GHC_EXPAND_IMPL
- //-----------------------------------------------------------------------------
- // 30.10.8.4.5 modifiers
- GHC_INLINE void path::clear() noexcept { _path.clear(); }
- GHC_INLINE path & path::make_preferred() {
- // as this filesystem implementation only uses generic_format
- // internally, this must be a no-op
- return *this;
- }
- GHC_INLINE path & path::remove_filename() {
- if (has_filename()) {
- _path.erase(_path.size() - filename()._path.size());
- }
- return *this;
- }
- GHC_INLINE path & path::replace_filename(const path & replacement) {
- remove_filename();
- return append(replacement);
- }
- GHC_INLINE path & path::replace_extension(const path & replacement) {
- if (has_extension()) {
- _path.erase(_path.size() - extension()._path.size());
- }
- if (!replacement.empty() && replacement._path[0] != '.') { _path += '.'; }
- return concat(replacement);
- }
- GHC_INLINE void path::swap(path & rhs) noexcept { _path.swap(rhs._path); }
- //-----------------------------------------------------------------------------
- // 30.10.8.4.6, native format observers
- #ifdef GHC_OS_WINDOWS
- GHC_INLINE path::impl_string_type path::native_impl() const {
- impl_string_type result;
- if (is_absolute() && _path.length() > MAX_PATH - 10) {
- // expand long Windows filenames with marker
- if (has_root_name() && _path[0] == '/') {
- result = "\\\\?\\UNC" + _path.substr(1);
- } else {
- result = "\\\\?\\" + _path;
- }
- } else {
- result = _path;
- }
- /*if (has_root_name() && root_name()._path[0] == '/') {
- return _path;
- }*/
- for (auto & c : result) {
- if (c == '/') { c = '\\'; }
- }
- return result;
- }
- #else
- GHC_INLINE const path::impl_string_type & path::native_impl() const {
- return _path;
- }
- #endif
- GHC_INLINE const path::string_type & path::native() const {
- #ifdef GHC_OS_WINDOWS
- #ifdef GHC_USE_WCHAR_T
- _native_cache = detail::fromUtf8<string_type>(native_impl());
- #else
- _native_cache = native_impl();
- #endif
- return _native_cache;
- #else
- return _path;
- #endif
- }
- GHC_INLINE const path::value_type * path::c_str() const {
- return native().c_str();
- }
- GHC_INLINE path::operator path::string_type() const { return native(); }
- #endif // GHC_EXPAND_IMPL
- template <class EcharT, class traits, class Allocator>
- inline std::basic_string<EcharT, traits, Allocator>
- path::string(const Allocator & a) const {
- return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(
- native_impl(), a);
- }
- #ifdef GHC_EXPAND_IMPL
- GHC_INLINE std::string path::string() const { return native_impl(); }
- GHC_INLINE std::wstring path::wstring() const {
- #ifdef GHC_USE_WCHAR_T
- return native();
- #else
- return detail::fromUtf8<std::wstring>(native());
- #endif
- }
- GHC_INLINE std::string path::u8string() const { return native_impl(); }
- GHC_INLINE std::u16string path::u16string() const {
- return detail::fromUtf8<std::u16string>(native_impl());
- }
- GHC_INLINE std::u32string path::u32string() const {
- return detail::fromUtf8<std::u32string>(native_impl());
- }
- #endif // GHC_EXPAND_IMPL
- //-----------------------------------------------------------------------------
- // 30.10.8.4.7, generic format observers
- template <class EcharT, class traits, class Allocator>
- inline std::basic_string<EcharT, traits, Allocator>
- path::generic_string(const Allocator & a) const {
- return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(
- _path, a);
- }
- #ifdef GHC_EXPAND_IMPL
- GHC_INLINE const std::string & path::generic_string() const {
- return _path;
- }
- GHC_INLINE std::wstring path::generic_wstring() const {
- return detail::fromUtf8<std::wstring>(_path);
- }
- GHC_INLINE std::string path::generic_u8string() const { return _path; }
- GHC_INLINE std::u16string path::generic_u16string() const {
- return detail::fromUtf8<std::u16string>(_path);
- }
- GHC_INLINE std::u32string path::generic_u32string() const {
- return detail::fromUtf8<std::u32string>(_path);
- }
- //-----------------------------------------------------------------------------
- // 30.10.8.4.8, compare
- GHC_INLINE int path::compare(const path & p) const noexcept {
- return native().compare(p.native());
- }
- GHC_INLINE int path::compare(const string_type & s) const {
- return native().compare(path(s).native());
- }
- #ifdef __cpp_lib_string_view
- GHC_INLINE int path::compare(std::basic_string_view<value_type> s) const {
- return native().compare(path(s).native());
- }
- #endif
- GHC_INLINE int path::compare(const value_type * s) const {
- return native().compare(path(s).native());
- }
- //-----------------------------------------------------------------------------
- // 30.10.8.4.9, decomposition
- GHC_INLINE path path::root_name() const {
- #ifdef GHC_OS_WINDOWS
- if (_path.length() >= 2 &&
- std::toupper(static_cast<unsigned char>(_path[0])) >= 'A' &&
- std::toupper(static_cast<unsigned char>(_path[0])) <= 'Z' &&
- _path[1] == ':') {
- return path(_path.substr(0, 2));
- }
- #endif
- if (_path.length() > 2 && _path[0] == '/' && _path[1] == '/' &&
- _path[2] != '/' && std::isprint(_path[2])) {
- impl_string_type::size_type pos = _path.find_first_of("/\\", 3);
- if (pos == impl_string_type::npos) {
- return path(_path);
- } else {
- return path(_path.substr(0, pos));
- }
- }
- return path();
- }
- GHC_INLINE path path::root_directory() const {
- path root = root_name();
- if (_path.length() > root._path.length() &&
- _path[root._path.length()] == '/') {
- return path("/");
- }
- return path();
- }
- GHC_INLINE path path::root_path() const {
- return root_name().generic_string() + root_directory().generic_string();
- }
- GHC_INLINE path path::relative_path() const {
- std::string root = root_path()._path;
- return path(_path.substr((std::min)(root.length(), _path.length())),
- generic_format);
- }
- GHC_INLINE path path::parent_path() const {
- if (has_relative_path()) {
- if (empty() || begin() == --end()) {
- return path();
- } else {
- path pp;
- for (string_type s :
- input_iterator_range<iterator>(begin(), --end())) {
- if (s == "/") {
- // don't use append to join a path-
- pp += s;
- } else {
- pp /= s;
- }
- }
- return pp;
- }
- } else {
- return *this;
- }
- }
- GHC_INLINE path path::filename() const {
- return relative_path().empty() ? path() : path(*--end());
- }
- GHC_INLINE path path::stem() const {
- impl_string_type fn = filename().string();
- if (fn != "." && fn != "..") {
- impl_string_type::size_type n = fn.rfind('.');
- if (n != impl_string_type::npos && n != 0) {
- return path{fn.substr(0, n)};
- }
- }
- return path{fn};
- }
- GHC_INLINE path path::extension() const {
- impl_string_type fn = filename().string();
- impl_string_type::size_type pos = fn.find_last_of('.');
- if (pos == std::string::npos || pos == 0) { return ""; }
- return fn.substr(pos);
- }
- //-----------------------------------------------------------------------------
- // 30.10.8.4.10, query
- GHC_INLINE bool path::empty() const noexcept { return _path.empty(); }
- GHC_INLINE bool path::has_root_name() const { return !root_name().empty(); }
- GHC_INLINE bool path::has_root_directory() const {
- return !root_directory().empty();
- }
- GHC_INLINE bool path::has_root_path() const { return !root_path().empty(); }
- GHC_INLINE bool path::has_relative_path() const {
- return !relative_path().empty();
- }
- GHC_INLINE bool path::has_parent_path() const {
- return !parent_path().empty();
- }
- GHC_INLINE bool path::has_filename() const { return !filename().empty(); }
- GHC_INLINE bool path::has_stem() const { return !stem().empty(); }
- GHC_INLINE bool path::has_extension() const { return !extension().empty(); }
- GHC_INLINE bool path::is_absolute() const {
- #ifdef GHC_OS_WINDOWS
- return has_root_name() && has_root_directory();
- #else
- return has_root_directory();
- #endif
- }
- GHC_INLINE bool path::is_relative() const { return !is_absolute(); }
- //-----------------------------------------------------------------------------
- // 30.10.8.4.11, generation
- GHC_INLINE path path::lexically_normal() const {
- path dest;
- bool lastDotDot = false;
- for (string_type s : *this) {
- if (s == ".") {
- dest /= "";
- continue;
- } else if (s == ".." && !dest.empty()) {
- auto root = root_path();
- if (dest == root) {
- continue;
- } else if (*(--dest.end()) != "..") {
- if (dest._path.back() == generic_separator) {
- dest._path.pop_back();
- }
- dest.remove_filename();
- continue;
- }
- }
- if (!(s.empty() && lastDotDot)) { dest /= s; }
- lastDotDot = s == "..";
- }
- if (dest.empty()) { dest = "."; }
- return dest;
- }
- GHC_INLINE path path::lexically_relative(const path & base) const {
- if (root_name() != base.root_name() ||
- is_absolute() != base.is_absolute() ||
- (!has_root_directory() && base.has_root_directory())) {
- return path();
- }
- const_iterator a = begin(), b = base.begin();
- while (a != end() && b != base.end() && *a == *b) {
- ++a;
- ++b;
- }
- if (a == end() && b == base.end()) { return path("."); }
- int count = 0;
- for (const auto & element :
- input_iterator_range<const_iterator>(b, base.end())) {
- if (element != "." && element != "" && element != "..") {
- ++count;
- } else if (element == "..") {
- --count;
- }
- }
- if (count < 0) { return path(); }
- path result;
- for (int i = 0; i < count; ++i) {
- result /= "..";
- }
- for (const auto & element :
- input_iterator_range<const_iterator>(a, end())) {
- result /= element;
- }
- return result;
- }
- GHC_INLINE path path::lexically_proximate(const path & base) const {
- path result = lexically_relative(base);
- return result.empty() ? *this : result;
- }
- //-----------------------------------------------------------------------------
- // 30.10.8.5, iterators
- GHC_INLINE path::iterator::iterator() {}
- GHC_INLINE path::iterator::iterator(
- const path::impl_string_type::const_iterator & first,
- const path::impl_string_type::const_iterator & last,
- const path::impl_string_type::const_iterator & pos)
- : _first(first), _last(last), _iter(pos) {
- updateCurrent();
- // find the position of a potential root directory slash
- #ifdef GHC_OS_WINDOWS
- if (_last - _first >= 3 &&
- std::toupper(static_cast<unsigned char>(*first)) >= 'A' &&
- std::toupper(static_cast<unsigned char>(*first)) <= 'Z' &&
- *(first + 1) == ':' && *(first + 2) == '/') {
- _root = _first + 2;
- } else
- #endif
- {
- if (_first != _last && *_first == '/') {
- if (_last - _first >= 2 && *(_first + 1) == '/' &&
- !(_last - _first >= 3 && *(_first + 2) == '/')) {
- _root = increment(_first);
- } else {
- _root = _first;
- }
- } else {
- _root = _last;
- }
- }
- }
- GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(
- const path::impl_string_type::const_iterator & pos) const {
- path::impl_string_type::const_iterator i = pos;
- bool fromStart = i == _first;
- if (i != _last) {
- // we can only sit on a slash if it is a network name or a root
- if (*i++ == '/') {
- if (i != _last && *i == '/') {
- if (fromStart && !(i + 1 != _last && *(i + 1) == '/')) {
- // leadind double slashes detected, treat this and the
- // following until a slash as one unit
- i = std::find(++i, _last, '/');
- } else {
- // skip redundant slashes
- while (i != _last && *i == '/') {
- ++i;
- }
- }
- }
- } else {
- if (fromStart && i != _last && *i == ':') {
- ++i;
- } else {
- i = std::find(i, _last, '/');
- }
- }
- }
- return i;
- }
- GHC_INLINE path::impl_string_type::const_iterator path::iterator::decrement(
- const path::impl_string_type::const_iterator & pos) const {
- path::impl_string_type::const_iterator i = pos;
- if (i != _first) {
- --i;
- // if this is now the root slash or the trailing slash, we are done,
- // else check for network name
- if (i != _root && (pos != _last || *i != '/')) {
- #ifdef GHC_OS_WINDOWS
- static const std::string seps = "/:";
- i = std::find_first_of(
- std::reverse_iterator<path::impl_string_type::const_iterator>(
- i),
- std::reverse_iterator<path::impl_string_type::const_iterator>(
- _first),
- seps.begin(), seps.end())
- .base();
- if (i > _first && *i == ':') { i++; }
- #else
- i = std::find(
- std::reverse_iterator<path::impl_string_type::const_iterator>(
- i),
- std::reverse_iterator<path::impl_string_type::const_iterator>(
- _first),
- '/')
- .base();
- #endif
- // Now we have to check if this is a network name
- if (i - _first == 2 && *_first == '/' && *(_first + 1) == '/') {
- i -= 2;
- }
- }
- }
- return i;
- }
- GHC_INLINE void path::iterator::updateCurrent() {
- if (_iter != _first && _iter != _last &&
- (*_iter == '/' && _iter != _root) && (_iter + 1 == _last)) {
- _current = "";
- } else {
- _current.assign(_iter, increment(_iter));
- if (_current.generic_string().size() > 1 &&
- _current.generic_string()[0] == '/' &&
- _current.generic_string()[_current.generic_string().size() - 1] ==
- '/') {
- // shrink successive slashes to one
- _current = "/";
- }
- }
- }
- GHC_INLINE path::iterator & path::iterator::operator++() {
- _iter = increment(_iter);
- while (_iter != _last && // we didn't reach the end
- _iter != _root && // this is not a root position
- *_iter == '/' && // we are on a slash
- (_iter + 1) != _last // the slash is not the last char
- ) {
- ++_iter;
- }
- updateCurrent();
- return *this;
- }
- GHC_INLINE path::iterator path::iterator::operator++(int) {
- path::iterator i{*this};
- ++(*this);
- return i;
- }
- GHC_INLINE path::iterator & path::iterator::operator--() {
- _iter = decrement(_iter);
- updateCurrent();
- return *this;
- }
- GHC_INLINE path::iterator path::iterator::operator--(int) {
- auto i = *this;
- --(*this);
- return i;
- }
- GHC_INLINE bool
- path::iterator::operator==(const path::iterator & other) const {
- return _iter == other._iter;
- }
- GHC_INLINE bool
- path::iterator::operator!=(const path::iterator & other) const {
- return _iter != other._iter;
- }
- GHC_INLINE path::iterator::reference path::iterator::operator*() const {
- return _current;
- }
- GHC_INLINE path::iterator::pointer path::iterator::operator->() const {
- return &_current;
- }
- GHC_INLINE path::iterator path::begin() const {
- return iterator(_path.begin(), _path.end(), _path.begin());
- }
- GHC_INLINE path::iterator path::end() const {
- return iterator(_path.begin(), _path.end(), _path.end());
- }
- //-----------------------------------------------------------------------------
- // 30.10.8.6, path non-member functions
- GHC_INLINE void swap(path & lhs, path & rhs) noexcept {
- swap(lhs._path, rhs._path);
- }
- GHC_INLINE size_t hash_value(const path & p) noexcept {
- return std::hash<std::string>()(p.generic_string());
- }
- GHC_INLINE bool operator==(const path & lhs, const path & rhs) noexcept {
- return lhs.generic_string() == rhs.generic_string();
- }
- GHC_INLINE bool operator!=(const path & lhs, const path & rhs) noexcept {
- return lhs.generic_string() != rhs.generic_string();
- }
- GHC_INLINE bool operator<(const path & lhs, const path & rhs) noexcept {
- return lhs.generic_string() < rhs.generic_string();
- }
- GHC_INLINE bool operator<=(const path & lhs, const path & rhs) noexcept {
- return lhs.generic_string() <= rhs.generic_string();
- }
- GHC_INLINE bool operator>(const path & lhs, const path & rhs) noexcept {
- return lhs.generic_string() > rhs.generic_string();
- }
- GHC_INLINE bool operator>=(const path & lhs, const path & rhs) noexcept {
- return lhs.generic_string() >= rhs.generic_string();
- }
- GHC_INLINE path operator/(const path & lhs, const path & rhs) {
- path result(lhs);
- result /= rhs;
- return result;
- }
- #endif // GHC_EXPAND_IMPL
- //-----------------------------------------------------------------------------
- // 30.10.8.6.1 path inserter and extractor
- template <class charT, class traits>
- inline std::basic_ostream<charT, traits> &
- operator<<(std::basic_ostream<charT, traits> & os, const path & p) {
- os << "\"";
- auto ps = p.string<charT, traits>();
- for (auto c : ps) {
- if (c == '"' || c == '\\') { os << '\\'; }
- os << c;
- }
- os << "\"";
- return os;
- }
- template <class charT, class traits>
- inline std::basic_istream<charT, traits> &
- operator>>(std::basic_istream<charT, traits> & is, path & p) {
- std::basic_string<charT, traits> tmp;
- charT c;
- is >> c;
- if (c == '"') {
- auto sf = is.flags();
- is >> std::noskipws;
- while (is) {
- auto c2 = is.get();
- if (is) {
- if (c2 == '\\') {
- c2 = is.get();
- if (is) { tmp += static_cast<charT>(c2); }
- } else if (c2 == '"') {
- break;
- } else {
- tmp += static_cast<charT>(c2);
- }
- }
- }
- if ((sf & std::ios_base::skipws) == std::ios_base::skipws) {
- is >> std::skipws;
- }
- p = path(tmp);
- } else {
- is >> tmp;
- p = path(static_cast<charT>(c) + tmp);
- }
- return is;
- }
- #ifdef GHC_EXPAND_IMPL
- //-----------------------------------------------------------------------------
- // 30.10.9 Class filesystem_error
- GHC_INLINE filesystem_error::filesystem_error(const std::string & what_arg,
- std::error_code ec)
- : std::system_error(ec, what_arg), _what_arg(what_arg), _ec(ec) {}
- GHC_INLINE filesystem_error::filesystem_error(const std::string & what_arg,
- const path & p1,
- std::error_code ec)
- : std::system_error(ec, what_arg), _what_arg(what_arg), _ec(ec),
- _p1(p1) {
- if (!_p1.empty()) { _what_arg += ": '" + _p1.u8string() + "'"; }
- }
- GHC_INLINE filesystem_error::filesystem_error(const std::string & what_arg,
- const path & p1,
- const path & p2,
- std::error_code ec)
- : std::system_error(ec, what_arg), _what_arg(what_arg), _ec(ec),
- _p1(p1), _p2(p2) {
- if (!_p1.empty()) { _what_arg += ": '" + _p1.u8string() + "'"; }
- if (!_p2.empty()) { _what_arg += ", '" + _p2.u8string() + "'"; }
- }
- GHC_INLINE const path & filesystem_error::path1() const noexcept {
- return _p1;
- }
- GHC_INLINE const path & filesystem_error::path2() const noexcept {
- return _p2;
- }
- GHC_INLINE const char * filesystem_error::what() const noexcept {
- return _what_arg.c_str();
- }
- //-----------------------------------------------------------------------------
- // 30.10.15, filesystem operations
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path absolute(const path & p) {
- std::error_code ec;
- path result = absolute(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE path absolute(const path & p, std::error_code & ec) {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- if (p.empty()) { return absolute(current_path(ec), ec) / ""; }
- ULONG size = ::GetFullPathNameW(p.wstring().c_str(), 0, 0, 0);
- if (size) {
- std::vector<wchar_t> buf(size, 0);
- ULONG s2 =
- GetFullPathNameW(p.wstring().c_str(), size, buf.data(), nullptr);
- if (s2 && s2 < size) {
- path result = path(std::wstring(buf.data(), s2));
- if (p.filename() == ".") { result /= "."; }
- return result;
- }
- }
- ec = detail::make_system_error();
- return path();
- #else
- path base = current_path(ec);
- if (!ec) {
- if (p.empty()) { return base / p; }
- if (p.has_root_name()) {
- if (p.has_root_directory()) {
- return p;
- } else {
- return p.root_name() / base.root_directory() /
- base.relative_path() / p.relative_path();
- }
- } else {
- if (p.has_root_directory()) {
- return base.root_name() / p;
- } else {
- return base / p;
- }
- }
- }
- ec = detail::make_system_error();
- return path();
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path canonical(const path & p) {
- std::error_code ec;
- auto result = canonical(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE path canonical(const path & p, std::error_code & ec) {
- if (p.empty()) {
- ec = detail::make_error_code(detail::portable_error::not_found);
- return path();
- }
- path work = p.is_absolute() ? p : absolute(p, ec);
- path root = work.root_path();
- path result;
- auto fs = status(work, ec);
- if (ec) { return path(); }
- if (fs.type() == file_type::not_found) {
- ec = detail::make_error_code(detail::portable_error::not_found);
- return path();
- }
- bool redo;
- do {
- redo = false;
- result.clear();
- for (auto pe : work) {
- if (pe.empty() || pe == ".") {
- continue;
- } else if (pe == "..") {
- result = result.parent_path();
- continue;
- } else if ((result / pe).string().length() <=
- root.string().length()) {
- result /= pe;
- continue;
- }
- auto sls = symlink_status(result / pe, ec);
- if (ec) { return path(); }
- if (is_symlink(sls)) {
- redo = true;
- auto target = read_symlink(result / pe, ec);
- if (ec) { return path(); }
- if (target.is_absolute()) {
- result = target;
- continue;
- } else {
- result /= target;
- continue;
- }
- } else {
- result /= pe;
- }
- }
- work = result;
- } while (redo);
- ec.clear();
- return result;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void copy(const path & from, const path & to) {
- copy(from, to, copy_options::none);
- }
- #endif
- GHC_INLINE void copy(const path & from, const path & to,
- std::error_code & ec) noexcept {
- copy(from, to, copy_options::none, ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void copy(const path & from, const path & to,
- copy_options options) {
- std::error_code ec;
- copy(from, to, options, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), from, to,
- ec);
- }
- }
- #endif
- GHC_INLINE void copy(const path & from, const path & to,
- copy_options options, std::error_code & ec) noexcept {
- std::error_code tec;
- file_status fs_from, fs_to;
- ec.clear();
- if ((options &
- (copy_options::skip_symlinks | copy_options::copy_symlinks |
- copy_options::create_symlinks)) != copy_options::none) {
- fs_from = symlink_status(from, ec);
- } else {
- fs_from = status(from, ec);
- }
- if (!exists(fs_from)) {
- if (!ec) {
- ec = detail::make_error_code(detail::portable_error::not_found);
- }
- return;
- }
- if ((options & (copy_options::skip_symlinks |
- copy_options::create_symlinks)) != copy_options::none) {
- fs_to = symlink_status(to, tec);
- } else {
- fs_to = status(to, tec);
- }
- if (is_other(fs_from) || is_other(fs_to) ||
- (is_directory(fs_from) && is_regular_file(fs_to)) ||
- (exists(fs_to) && equivalent(from, to, ec))) {
- ec = detail::make_error_code(detail::portable_error::invalid_argument);
- } else if (is_symlink(fs_from)) {
- if ((options & copy_options::skip_symlinks) == copy_options::none) {
- if (!exists(fs_to) &&
- (options & copy_options::copy_symlinks) != copy_options::none) {
- copy_symlink(from, to, ec);
- } else {
- ec = detail::make_error_code(
- detail::portable_error::invalid_argument);
- }
- }
- } else if (is_regular_file(fs_from)) {
- if ((options & copy_options::directories_only) == copy_options::none) {
- if ((options & copy_options::create_symlinks) != copy_options::none) {
- create_symlink(from.is_absolute() ? from : canonical(from, ec), to,
- ec);
- }
- #ifndef GHC_OS_WEB
- else if ((options & copy_options::create_hard_links) !=
- copy_options::none) {
- create_hard_link(from, to, ec);
- }
- #endif
- else if (is_directory(fs_to)) {
- copy_file(from, to / from.filename(), options, ec);
- } else {
- copy_file(from, to, options, ec);
- }
- }
- }
- #ifdef LWG_2682_BEHAVIOUR
- else if (is_directory(fs_from) &&
- (options & copy_options::create_symlinks) !=
- copy_options::none) {
- ec = detail::make_error_code(detail::portable_error::is_a_directory);
- }
- #endif
- else if (is_directory(fs_from) &&
- (options == copy_options::none ||
- (options & copy_options::recursive) != copy_options::none)) {
- if (!exists(fs_to)) {
- create_directory(to, from, ec);
- if (ec) { return; }
- }
- for (auto iter = directory_iterator(from, ec);
- iter != directory_iterator(); iter.increment(ec)) {
- if (!ec) {
- copy(iter->path(), to / iter->path().filename(),
- options | static_cast<copy_options>(0x8000), ec);
- }
- if (ec) { return; }
- }
- }
- return;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool copy_file(const path & from, const path & to) {
- return copy_file(from, to, copy_options::none);
- }
- #endif
- GHC_INLINE bool copy_file(const path & from, const path & to,
- std::error_code & ec) noexcept {
- return copy_file(from, to, copy_options::none, ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool copy_file(const path & from, const path & to,
- copy_options option) {
- std::error_code ec;
- auto result = copy_file(from, to, option, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), from, to,
- ec);
- }
- return result;
- }
- #endif
- GHC_INLINE bool copy_file(const path & from, const path & to,
- copy_options options,
- std::error_code & ec) noexcept {
- std::error_code tecf, tect;
- auto sf = status(from, tecf);
- auto st = status(to, tect);
- bool overwrite = false;
- ec.clear();
- if (!is_regular_file(sf)) {
- ec = tecf;
- return false;
- }
- if (exists(st) &&
- (!is_regular_file(st) || equivalent(from, to, ec) ||
- (options &
- (copy_options::skip_existing | copy_options::overwrite_existing |
- copy_options::update_existing)) == copy_options::none)) {
- ec = tect ? tect
- : detail::make_error_code(detail::portable_error::exists);
- return false;
- }
- if (exists(st)) {
- if ((options & copy_options::update_existing) ==
- copy_options::update_existing) {
- auto from_time = last_write_time(from, ec);
- if (ec) {
- ec = detail::make_system_error();
- return false;
- }
- auto to_time = last_write_time(to, ec);
- if (ec) {
- ec = detail::make_system_error();
- return false;
- }
- if (from_time <= to_time) { return false; }
- }
- overwrite = true;
- }
- #ifdef GHC_OS_WINDOWS
- if (!::CopyFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(),
- detail::fromUtf8<std::wstring>(to.u8string()).c_str(),
- !overwrite)) {
- ec = detail::make_system_error();
- return false;
- }
- return true;
- #else
- std::vector<char> buffer(16384, '\0');
- int in = -1, out = -1;
- if ((in = ::open(from.c_str(), O_RDONLY)) < 0) {
- ec = detail::make_system_error();
- return false;
- }
- int mode = O_CREAT | O_WRONLY | O_TRUNC;
- if (!overwrite) { mode |= O_EXCL; }
- if ((out = ::open(to.c_str(), mode,
- static_cast<int>(sf.permissions() & perms::all))) < 0) {
- ec = detail::make_system_error();
- ::close(in);
- return false;
- }
- ssize_t br, bw;
- while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
- ssize_t offset = 0;
- do {
- if ((bw = ::write(out, buffer.data() + offset,
- static_cast<size_t>(br))) > 0) {
- br -= bw;
- offset += bw;
- } else if (bw < 0) {
- ec = detail::make_system_error();
- ::close(in);
- ::close(out);
- return false;
- }
- } while (br);
- }
- ::close(in);
- ::close(out);
- return true;
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void copy_symlink(const path & existing_symlink,
- const path & new_symlink) {
- std::error_code ec;
- copy_symlink(existing_symlink, new_symlink, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()),
- existing_symlink, new_symlink, ec);
- }
- }
- #endif
- GHC_INLINE void copy_symlink(const path & existing_symlink,
- const path & new_symlink,
- std::error_code & ec) noexcept {
- ec.clear();
- auto to = read_symlink(existing_symlink, ec);
- if (!ec) {
- if (exists(to, ec) && is_directory(to, ec)) {
- create_directory_symlink(to, new_symlink, ec);
- } else {
- create_symlink(to, new_symlink, ec);
- }
- }
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool create_directories(const path & p) {
- std::error_code ec;
- auto result = create_directories(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE bool create_directories(const path & p,
- std::error_code & ec) noexcept {
- path current;
- ec.clear();
- bool didCreate = false;
- for (path::string_type part : p) {
- current /= part;
- if (current != p.root_name() && current != p.root_path()) {
- std::error_code tec;
- auto fs = status(current, tec);
- if (tec && fs.type() != file_type::not_found) {
- ec = tec;
- return false;
- }
- if (!exists(fs)) {
- create_directory(current, ec);
- if (ec) {
- std::error_code tmp_ec;
- if (is_directory(current, tmp_ec)) {
- ec.clear();
- } else {
- return false;
- }
- }
- didCreate = true;
- }
- #ifndef LWG_2935_BEHAVIOUR
- else if (!is_directory(fs)) {
- ec = detail::make_error_code(detail::portable_error::exists);
- return false;
- }
- #endif
- }
- }
- return didCreate;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool create_directory(const path & p) {
- std::error_code ec;
- auto result = create_directory(p, path(), ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE bool create_directory(const path & p,
- std::error_code & ec) noexcept {
- return create_directory(p, path(), ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool create_directory(const path & p, const path & attributes) {
- std::error_code ec;
- auto result = create_directory(p, attributes, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE bool create_directory(const path & p, const path & attributes,
- std::error_code & ec) noexcept {
- std::error_code tec;
- ec.clear();
- auto fs = status(p, tec);
- #ifdef LWG_2935_BEHAVIOUR
- if (status_known(fs) && exists(fs)) { return false; }
- #else
- if (status_known(fs) && exists(fs) && is_directory(fs)) { return false; }
- #endif
- #ifdef GHC_OS_WINDOWS
- if (!attributes.empty()) {
- if (!::CreateDirectoryExW(
- detail::fromUtf8<std::wstring>(attributes.u8string()).c_str(),
- detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
- ec = detail::make_system_error();
- return false;
- }
- } else if (!::CreateDirectoryW(
- detail::fromUtf8<std::wstring>(p.u8string()).c_str(),
- NULL)) {
- ec = detail::make_system_error();
- return false;
- }
- #else
- ::mode_t attribs = static_cast<mode_t>(perms::all);
- if (!attributes.empty()) {
- struct ::stat fileStat;
- if (::stat(attributes.c_str(), &fileStat) != 0) {
- ec = detail::make_system_error();
- return false;
- }
- attribs = fileStat.st_mode;
- }
- if (::mkdir(p.c_str(), attribs) != 0) {
- ec = detail::make_system_error();
- return false;
- }
- #endif
- return true;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void create_directory_symlink(const path & to,
- const path & new_symlink) {
- std::error_code ec;
- create_directory_symlink(to, new_symlink, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), to,
- new_symlink, ec);
- }
- }
- #endif
- GHC_INLINE void create_directory_symlink(const path & to,
- const path & new_symlink,
- std::error_code & ec) noexcept {
- detail::create_symlink(to, new_symlink, true, ec);
- }
- #ifndef GHC_OS_WEB
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void create_hard_link(const path & to,
- const path & new_hard_link) {
- std::error_code ec;
- create_hard_link(to, new_hard_link, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), to,
- new_hard_link, ec);
- }
- }
- #endif
- GHC_INLINE void create_hard_link(const path & to,
- const path & new_hard_link,
- std::error_code & ec) noexcept {
- detail::create_hardlink(to, new_hard_link, ec);
- }
- #endif
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void create_symlink(const path & to, const path & new_symlink) {
- std::error_code ec;
- create_symlink(to, new_symlink, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), to,
- new_symlink, ec);
- }
- }
- #endif
- GHC_INLINE void create_symlink(const path & to, const path & new_symlink,
- std::error_code & ec) noexcept {
- detail::create_symlink(to, new_symlink, false, ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path current_path() {
- std::error_code ec;
- auto result = current_path(ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), ec);
- }
- return result;
- }
- #endif
- GHC_INLINE path current_path(std::error_code & ec) {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- DWORD pathlen = ::GetCurrentDirectoryW(0, 0);
- std::unique_ptr<wchar_t[]> buffer(new wchar_t[size_t(pathlen) + 1]);
- if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) {
- ec = detail::make_system_error();
- return path();
- }
- return path(std::wstring(buffer.get()), path::native_format);
- #else
- size_t pathlen = static_cast<size_t>(
- std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
- std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
- if (::getcwd(buffer.get(), pathlen) == nullptr) {
- ec = detail::make_system_error();
- return path();
- }
- return path(buffer.get());
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void current_path(const path & p) {
- std::error_code ec;
- current_path(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- }
- #endif
- GHC_INLINE void current_path(const path & p,
- std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- if (!::SetCurrentDirectoryW(
- detail::fromUtf8<std::wstring>(p.u8string()).c_str())) {
- ec = detail::make_system_error();
- }
- #else
- if (::chdir(p.string().c_str()) == -1) {
- ec = detail::make_system_error();
- }
- #endif
- }
- GHC_INLINE bool exists(file_status s) noexcept {
- return status_known(s) && s.type() != file_type::not_found;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool exists(const path & p) { return exists(status(p)); }
- #endif
- GHC_INLINE bool exists(const path & p, std::error_code & ec) noexcept {
- file_status s = status(p, ec);
- if (status_known(s)) { ec.clear(); }
- return exists(s);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool equivalent(const path & p1, const path & p2) {
- std::error_code ec;
- bool result = equivalent(p1, p2, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p1, p2, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE bool equivalent(const path & p1, const path & p2,
- std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- std::shared_ptr<void> file1(
- ::CreateFileW(p1.wstring().c_str(), 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0),
- CloseHandle);
- auto e1 = ::GetLastError();
- std::shared_ptr<void> file2(
- ::CreateFileW(p2.wstring().c_str(), 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0),
- CloseHandle);
- if (file1.get() == INVALID_HANDLE_VALUE ||
- file2.get() == INVALID_HANDLE_VALUE) {
- #ifdef LWG_2937_BEHAVIOUR
- ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
- #else
- if (file1 == file2) {
- ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
- }
- #endif
- return false;
- }
- BY_HANDLE_FILE_INFORMATION inf1, inf2;
- if (!::GetFileInformationByHandle(file1.get(), &inf1)) {
- ec = detail::make_system_error();
- return false;
- }
- if (!::GetFileInformationByHandle(file2.get(), &inf2)) {
- ec = detail::make_system_error();
- return false;
- }
- return inf1.ftLastWriteTime.dwLowDateTime ==
- inf2.ftLastWriteTime.dwLowDateTime &&
- inf1.ftLastWriteTime.dwHighDateTime ==
- inf2.ftLastWriteTime.dwHighDateTime &&
- inf1.nFileIndexHigh == inf2.nFileIndexHigh &&
- inf1.nFileIndexLow == inf2.nFileIndexLow &&
- inf1.nFileSizeHigh == inf2.nFileSizeHigh &&
- inf1.nFileSizeLow == inf2.nFileSizeLow &&
- inf1.dwVolumeSerialNumber == inf2.dwVolumeSerialNumber;
- #else
- struct ::stat s1, s2;
- auto rc1 = ::stat(p1.c_str(), &s1);
- auto e1 = errno;
- auto rc2 = ::stat(p2.c_str(), &s2);
- if (rc1 || rc2) {
- #ifdef LWG_2937_BEHAVIOUR
- ec = detail::make_system_error(e1 ? e1 : errno);
- #else
- if (rc1 && rc2) { ec = detail::make_system_error(e1 ? e1 : errno); }
- #endif
- return false;
- }
- return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino &&
- s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE uintmax_t file_size(const path & p) {
- std::error_code ec;
- auto result = file_size(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE uintmax_t file_size(const path & p,
- std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- WIN32_FILE_ATTRIBUTE_DATA attr;
- if (!GetFileAttributesExW(
- detail::fromUtf8<std::wstring>(p.u8string()).c_str(),
- GetFileExInfoStandard, &attr)) {
- ec = detail::make_system_error();
- return static_cast<uintmax_t>(-1);
- }
- return static_cast<uintmax_t>(attr.nFileSizeHigh)
- << (sizeof(attr.nFileSizeHigh) * 8) |
- attr.nFileSizeLow;
- #else
- struct ::stat fileStat;
- if (::stat(p.c_str(), &fileStat) == -1) {
- ec = detail::make_system_error();
- return static_cast<uintmax_t>(-1);
- }
- return static_cast<uintmax_t>(fileStat.st_size);
- #endif
- }
- #ifndef GHC_OS_WEB
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE uintmax_t hard_link_count(const path & p) {
- std::error_code ec;
- auto result = hard_link_count(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE uintmax_t hard_link_count(const path & p,
- std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- uintmax_t result = static_cast<uintmax_t>(-1);
- std::shared_ptr<void> file(
- ::CreateFileW(p.wstring().c_str(), 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0),
- CloseHandle);
- BY_HANDLE_FILE_INFORMATION inf;
- if (file.get() == INVALID_HANDLE_VALUE) {
- ec = detail::make_system_error();
- } else {
- if (!::GetFileInformationByHandle(file.get(), &inf)) {
- ec = detail::make_system_error();
- } else {
- result = inf.nNumberOfLinks;
- }
- }
- return result;
- #else
- uintmax_t result = 0;
- file_status fs =
- detail::status_ex(p, ec, nullptr, nullptr, &result, nullptr);
- if (fs.type() == file_type::not_found) {
- ec = detail::make_error_code(detail::portable_error::not_found);
- }
- return ec ? static_cast<uintmax_t>(-1) : result;
- #endif
- }
- #endif
- GHC_INLINE bool is_block_file(file_status s) noexcept {
- return s.type() == file_type::block;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_block_file(const path & p) {
- return is_block_file(status(p));
- }
- #endif
- GHC_INLINE bool is_block_file(const path & p,
- std::error_code & ec) noexcept {
- return is_block_file(status(p, ec));
- }
- GHC_INLINE bool is_character_file(file_status s) noexcept {
- return s.type() == file_type::character;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_character_file(const path & p) {
- return is_character_file(status(p));
- }
- #endif
- GHC_INLINE bool is_character_file(const path & p,
- std::error_code & ec) noexcept {
- return is_character_file(status(p, ec));
- }
- GHC_INLINE bool is_directory(file_status s) noexcept {
- return s.type() == file_type::directory;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_directory(const path & p) {
- return is_directory(status(p));
- }
- #endif
- GHC_INLINE bool is_directory(const path & p,
- std::error_code & ec) noexcept {
- return is_directory(status(p, ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_empty(const path & p) {
- if (is_directory(p)) {
- return directory_iterator(p) == directory_iterator();
- } else {
- return file_size(p) == 0;
- }
- }
- #endif
- GHC_INLINE bool is_empty(const path & p, std::error_code & ec) noexcept {
- auto fs = status(p, ec);
- if (ec) { return false; }
- if (is_directory(fs)) {
- directory_iterator iter(p, ec);
- if (ec) { return false; }
- return iter == directory_iterator();
- } else {
- auto sz = file_size(p, ec);
- if (ec) { return false; }
- return sz == 0;
- }
- }
- GHC_INLINE bool is_fifo(file_status s) noexcept {
- return s.type() == file_type::fifo;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_fifo(const path & p) { return is_fifo(status(p)); }
- #endif
- GHC_INLINE bool is_fifo(const path & p, std::error_code & ec) noexcept {
- return is_fifo(status(p, ec));
- }
- GHC_INLINE bool is_other(file_status s) noexcept {
- return exists(s) && !is_regular_file(s) && !is_directory(s) &&
- !is_symlink(s);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_other(const path & p) { return is_other(status(p)); }
- #endif
- GHC_INLINE bool is_other(const path & p, std::error_code & ec) noexcept {
- return is_other(status(p, ec));
- }
- GHC_INLINE bool is_regular_file(file_status s) noexcept {
- return s.type() == file_type::regular;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_regular_file(const path & p) {
- return is_regular_file(status(p));
- }
- #endif
- GHC_INLINE bool is_regular_file(const path & p,
- std::error_code & ec) noexcept {
- return is_regular_file(status(p, ec));
- }
- GHC_INLINE bool is_socket(file_status s) noexcept {
- return s.type() == file_type::socket;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_socket(const path & p) { return is_socket(status(p)); }
- #endif
- GHC_INLINE bool is_socket(const path & p, std::error_code & ec) noexcept {
- return is_socket(status(p, ec));
- }
- GHC_INLINE bool is_symlink(file_status s) noexcept {
- return s.type() == file_type::symlink;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool is_symlink(const path & p) {
- return is_symlink(symlink_status(p));
- }
- #endif
- GHC_INLINE bool is_symlink(const path & p, std::error_code & ec) noexcept {
- return is_symlink(symlink_status(p, ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE file_time_type last_write_time(const path & p) {
- std::error_code ec;
- auto result = last_write_time(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE file_time_type last_write_time(const path & p,
- std::error_code & ec) noexcept {
- time_t result = 0;
- ec.clear();
- file_status fs =
- detail::status_ex(p, ec, nullptr, nullptr, nullptr, &result);
- return ec ? (file_time_type::min)()
- : std::chrono::system_clock::from_time_t(result);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void last_write_time(const path & p, file_time_type new_time) {
- std::error_code ec;
- last_write_time(p, new_time, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- }
- #endif
- GHC_INLINE void last_write_time(const path & p, file_time_type new_time,
- std::error_code & ec) noexcept {
- ec.clear();
- auto d = new_time.time_since_epoch();
- #ifdef GHC_OS_WINDOWS
- std::shared_ptr<void> file(
- ::CreateFileW(p.wstring().c_str(), FILE_WRITE_ATTRIBUTES,
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL),
- ::CloseHandle);
- FILETIME ft;
- auto tt =
- std::chrono::duration_cast<std::chrono::microseconds>(d).count() *
- 10 +
- 116444736000000000;
- ft.dwLowDateTime = static_cast<DWORD>(tt);
- ft.dwHighDateTime = static_cast<DWORD>(tt >> 32);
- if (!::SetFileTime(file.get(), 0, 0, &ft)) {
- ec = detail::make_system_error();
- }
- #elif defined(GHC_OS_MACOS)
- #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
- #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
- struct ::stat fs;
- if (::stat(p.c_str(), &fs) == 0) {
- struct ::timeval tv[2];
- tv[0].tv_sec = fs.st_atimespec.tv_sec;
- tv[0].tv_usec = static_cast<int>(fs.st_atimespec.tv_nsec / 1000);
- tv[1].tv_sec =
- std::chrono::duration_cast<std::chrono::seconds>(d).count();
- tv[1].tv_usec = static_cast<int>(
- std::chrono::duration_cast<std::chrono::microseconds>(d).count() %
- 1000000);
- if (::utimes(p.c_str(), tv) == 0) { return; }
- }
- ec = detail::make_system_error();
- return;
- #else
- struct ::timespec times[2];
- times[0].tv_sec = 0;
- times[0].tv_nsec = UTIME_OMIT;
- times[1].tv_sec =
- std::chrono::duration_cast<std::chrono::seconds>(d).count();
- times[1].tv_nsec =
- 0; // std::chrono::duration_cast<std::chrono::nanoseconds>(d).count()
- // % 1000000000;
- if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
- ec = detail::make_system_error();
- }
- return;
- #endif
- #endif
- #else
- #ifndef UTIME_OMIT
- #define UTIME_OMIT ((1l << 30) - 2l)
- #endif
- struct ::timespec times[2];
- times[0].tv_sec = 0;
- times[0].tv_nsec = UTIME_OMIT;
- times[1].tv_sec = static_cast<decltype(times[1].tv_sec)>(
- std::chrono::duration_cast<std::chrono::seconds>(d).count());
- times[1].tv_nsec = static_cast<decltype(times[1].tv_nsec)>(
- std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() %
- 1000000000);
- #if defined(__ANDROID_API__) && __ANDROID_API__ < 12
- if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times,
- AT_SYMLINK_NOFOLLOW) != 0) {
- #else
- if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
- #endif
- ec = detail::make_system_error();
- }
- return;
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void permissions(const path & p, perms prms, perm_options opts) {
- std::error_code ec;
- permissions(p, prms, opts, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- }
- #endif
- GHC_INLINE void permissions(const path & p, perms prms,
- std::error_code & ec) noexcept {
- permissions(p, prms, perm_options::replace, ec);
- }
- GHC_INLINE void permissions(const path & p, perms prms, perm_options opts,
- std::error_code & ec) {
- if (static_cast<int>(opts & (perm_options::replace | perm_options::add |
- perm_options::remove)) == 0) {
- ec = detail::make_error_code(detail::portable_error::invalid_argument);
- return;
- }
- auto fs = symlink_status(p, ec);
- if ((opts & perm_options::replace) != perm_options::replace) {
- if ((opts & perm_options::add) == perm_options::add) {
- prms = fs.permissions() | prms;
- } else {
- prms = fs.permissions() & ~prms;
- }
- }
- #ifdef GHC_OS_WINDOWS
- #ifdef __GNUC__
- auto oldAttr = GetFileAttributesW(p.wstring().c_str());
- if (oldAttr != INVALID_FILE_ATTRIBUTES) {
- DWORD newAttr =
- ((prms & perms::owner_write) == perms::owner_write)
- ? oldAttr & ~(static_cast<DWORD>(FILE_ATTRIBUTE_READONLY))
- : oldAttr | FILE_ATTRIBUTE_READONLY;
- if (oldAttr == newAttr ||
- SetFileAttributesW(p.wstring().c_str(), newAttr)) {
- return;
- }
- }
- ec = detail::make_system_error();
- #else
- int mode = 0;
- if ((prms & perms::owner_read) == perms::owner_read) { mode |= _S_IREAD; }
- if ((prms & perms::owner_write) == perms::owner_write) {
- mode |= _S_IWRITE;
- }
- if (::_wchmod(p.wstring().c_str(), mode) != 0) {
- ec = detail::make_system_error();
- }
- #endif
- #else
- if ((opts & perm_options::nofollow) != perm_options::nofollow) {
- if (::chmod(p.c_str(), static_cast<mode_t>(prms)) != 0) {
- ec = detail::make_system_error();
- }
- }
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path proximate(const path & p, std::error_code & ec) {
- return proximate(p, current_path(), ec);
- }
- #endif
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path proximate(const path & p, const path & base) {
- return weakly_canonical(p).lexically_proximate(weakly_canonical(base));
- }
- #endif
- GHC_INLINE path proximate(const path & p, const path & base,
- std::error_code & ec) {
- return weakly_canonical(p, ec).lexically_proximate(
- weakly_canonical(base, ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path read_symlink(const path & p) {
- std::error_code ec;
- auto result = read_symlink(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE path read_symlink(const path & p, std::error_code & ec) {
- file_status fs = symlink_status(p, ec);
- if (fs.type() != file_type::symlink) {
- ec = detail::make_error_code(detail::portable_error::invalid_argument);
- return path();
- }
- auto result = detail::resolveSymlink(p, ec);
- return ec ? path() : result;
- }
- GHC_INLINE path relative(const path & p, std::error_code & ec) {
- return relative(p, current_path(ec), ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path relative(const path & p, const path & base) {
- return weakly_canonical(p).lexically_relative(weakly_canonical(base));
- }
- #endif
- GHC_INLINE path relative(const path & p, const path & base,
- std::error_code & ec) {
- return weakly_canonical(p, ec).lexically_relative(
- weakly_canonical(base, ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool remove(const path & p) {
- std::error_code ec;
- auto result = remove(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE bool remove(const path & p, std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- std::wstring np = detail::fromUtf8<std::wstring>(p.u8string());
- DWORD attr = GetFileAttributesW(np.c_str());
- if (attr == INVALID_FILE_ATTRIBUTES) {
- auto error = ::GetLastError();
- if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
- return false;
- }
- ec = detail::make_system_error(error);
- }
- if (!ec) {
- if (attr & FILE_ATTRIBUTE_DIRECTORY) {
- if (!RemoveDirectoryW(np.c_str())) {
- ec = detail::make_system_error();
- }
- } else {
- if (!DeleteFileW(np.c_str())) { ec = detail::make_system_error(); }
- }
- }
- #else
- if (::remove(p.c_str()) == -1) {
- auto error = errno;
- if (error == ENOENT) { return false; }
- ec = detail::make_system_error();
- }
- #endif
- return ec ? false : true;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE uintmax_t remove_all(const path & p) {
- std::error_code ec;
- auto result = remove_all(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE uintmax_t remove_all(const path & p,
- std::error_code & ec) noexcept {
- ec.clear();
- uintmax_t count = 0;
- if (p == "/") {
- ec = detail::make_error_code(detail::portable_error::not_supported);
- return static_cast<uintmax_t>(-1);
- }
- std::error_code tec;
- auto fs = status(p, tec);
- if (exists(fs) && is_directory(fs)) {
- for (auto iter = directory_iterator(p, ec);
- iter != directory_iterator(); iter.increment(ec)) {
- if (ec) { break; }
- bool is_symlink_result = iter->is_symlink(ec);
- if (ec) return static_cast<uintmax_t>(-1);
- bool is_directory_result = iter->is_directory(ec);
- if (ec) return static_cast<uintmax_t>(-1);
- if (!is_symlink_result && is_directory_result) {
- count += remove_all(iter->path(), ec);
- if (ec) { return static_cast<uintmax_t>(-1); }
- } else {
- remove(iter->path(), ec);
- if (ec) { return static_cast<uintmax_t>(-1); }
- ++count;
- }
- }
- }
- if (!ec) {
- if (remove(p, ec)) { ++count; }
- }
- if (ec) { return static_cast<uintmax_t>(-1); }
- return count;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void rename(const path & from, const path & to) {
- std::error_code ec;
- rename(from, to, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), from, to,
- ec);
- }
- }
- #endif
- GHC_INLINE void rename(const path & from, const path & to,
- std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- if (from != to) {
- if (!MoveFileExW(
- detail::fromUtf8<std::wstring>(from.u8string()).c_str(),
- detail::fromUtf8<std::wstring>(to.u8string()).c_str(),
- (DWORD)MOVEFILE_REPLACE_EXISTING)) {
- ec = detail::make_system_error();
- }
- }
- #else
- if (from != to) {
- if (::rename(from.c_str(), to.c_str()) != 0) {
- ec = detail::make_system_error();
- }
- }
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void resize_file(const path & p, uintmax_t size) {
- std::error_code ec;
- resize_file(p, size, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- }
- #endif
- GHC_INLINE void resize_file(const path & p, uintmax_t size,
- std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- LARGE_INTEGER lisize;
- lisize.QuadPart = static_cast<LONGLONG>(size);
- if (lisize.QuadPart < 0) {
- #ifdef ERROR_FILE_TOO_LARGE
- ec = detail::make_system_error(ERROR_FILE_TOO_LARGE);
- #else
- ec = detail::make_system_error(223);
- #endif
- return;
- }
- std::shared_ptr<void> file(
- CreateFileW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(),
- GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL),
- CloseHandle);
- if (file.get() == INVALID_HANDLE_VALUE) {
- ec = detail::make_system_error();
- } else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 ||
- SetEndOfFile(file.get()) == 0) {
- ec = detail::make_system_error();
- }
- #else
- if (::truncate(p.c_str(), static_cast<off_t>(size)) != 0) {
- ec = detail::make_system_error();
- }
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE space_info space(const path & p) {
- std::error_code ec;
- auto result = space(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE space_info space(const path & p, std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- ULARGE_INTEGER freeBytesAvailableToCaller = {{ 0, 0 }};
- ULARGE_INTEGER totalNumberOfBytes = {{ 0, 0 }};
- ULARGE_INTEGER totalNumberOfFreeBytes = {{ 0, 0 }};
- if (!GetDiskFreeSpaceExW(
- detail::fromUtf8<std::wstring>(p.u8string()).c_str(),
- &freeBytesAvailableToCaller, &totalNumberOfBytes,
- &totalNumberOfFreeBytes)) {
- ec = detail::make_system_error();
- return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1),
- static_cast<uintmax_t>(-1)};
- }
- return {static_cast<uintmax_t>(totalNumberOfBytes.QuadPart),
- static_cast<uintmax_t>(totalNumberOfFreeBytes.QuadPart),
- static_cast<uintmax_t>(freeBytesAvailableToCaller.QuadPart)};
- #else
- struct ::statvfs sfs;
- if (::statvfs(p.c_str(), &sfs) != 0) {
- ec = detail::make_system_error();
- return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1),
- static_cast<uintmax_t>(-1)};
- }
- return {static_cast<uintmax_t>(sfs.f_blocks * sfs.f_frsize),
- static_cast<uintmax_t>(sfs.f_bfree * sfs.f_frsize),
- static_cast<uintmax_t>(sfs.f_bavail * sfs.f_frsize)};
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE file_status status(const path & p) {
- std::error_code ec;
- auto result = status(p, ec);
- if (result.type() == file_type::none) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE file_status status(const path & p,
- std::error_code & ec) noexcept {
- return detail::status_ex(p, ec);
- }
- GHC_INLINE bool status_known(file_status s) noexcept {
- return s.type() != file_type::none;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE file_status symlink_status(const path & p) {
- std::error_code ec;
- auto result = symlink_status(p, ec);
- if (result.type() == file_type::none) {
- throw filesystem_error(detail::systemErrorText(ec.value()), ec);
- }
- return result;
- }
- #endif
- GHC_INLINE file_status symlink_status(const path & p,
- std::error_code & ec) noexcept {
- return detail::symlink_status_ex(p, ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path temp_directory_path() {
- std::error_code ec;
- path result = temp_directory_path(ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), ec);
- }
- return result;
- }
- #endif
- GHC_INLINE path temp_directory_path(std::error_code & ec) noexcept {
- ec.clear();
- #ifdef GHC_OS_WINDOWS
- wchar_t buffer[512];
- auto rc = GetTempPathW(511, buffer);
- if (!rc || rc > 511) {
- ec = detail::make_system_error();
- return path();
- }
- return path(std::wstring(buffer));
- #else
- static const char * temp_vars[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR",
- nullptr};
- const char * temp_path = nullptr;
- for (auto temp_name = temp_vars; *temp_name != nullptr; ++temp_name) {
- temp_path = std::getenv(*temp_name);
- if (temp_path) { return path(temp_path); }
- }
- return path("/tmp");
- #endif
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE path weakly_canonical(const path & p) {
- std::error_code ec;
- auto result = weakly_canonical(p, ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
- }
- return result;
- }
- #endif
- GHC_INLINE path weakly_canonical(const path & p,
- std::error_code & ec) noexcept {
- path result;
- ec.clear();
- bool scan = true;
- for (auto pe : p) {
- if (scan) {
- std::error_code tec;
- if (exists(result / pe, tec)) {
- result /= pe;
- } else {
- if (ec) { return path(); }
- scan = false;
- if (!result.empty()) {
- result = canonical(result, ec) / pe;
- if (ec) { break; }
- } else {
- result /= pe;
- }
- }
- } else {
- result /= pe;
- }
- }
- if (scan) {
- if (!result.empty()) { result = canonical(result, ec); }
- }
- return ec ? path() : result.lexically_normal();
- }
- //-----------------------------------------------------------------------------
- // 30.10.11 class file_status
- // 30.10.11.1 constructors and destructor
- GHC_INLINE file_status::file_status() noexcept
- : file_status(file_type::none) {}
- GHC_INLINE file_status::file_status(file_type ft, perms prms) noexcept
- : _type(ft), _perms(prms) {}
- GHC_INLINE file_status::file_status(const file_status & other) noexcept
- : _type(other._type), _perms(other._perms) {}
- GHC_INLINE file_status::file_status(file_status && other) noexcept
- : _type(other._type), _perms(other._perms) {}
- GHC_INLINE file_status::~file_status() {}
- // assignments:
- GHC_INLINE file_status &
- file_status::operator=(const file_status & rhs) noexcept {
- _type = rhs._type;
- _perms = rhs._perms;
- return *this;
- }
- GHC_INLINE file_status &
- file_status::operator=(file_status && rhs) noexcept {
- _type = rhs._type;
- _perms = rhs._perms;
- return *this;
- }
- // 30.10.11.3 modifiers
- GHC_INLINE void file_status::type(file_type ft) noexcept { _type = ft; }
- GHC_INLINE void file_status::permissions(perms prms) noexcept {
- _perms = prms;
- }
- // 30.10.11.2 observers
- GHC_INLINE file_type file_status::type() const noexcept { return _type; }
- GHC_INLINE perms file_status::permissions() const noexcept {
- return _perms;
- }
- //-----------------------------------------------------------------------------
- // 30.10.12 class directory_entry
- // 30.10.12.1 constructors and destructor
- // directory_entry::directory_entry() noexcept = default;
- // directory_entry::directory_entry(const directory_entry&) = default;
- // directory_entry::directory_entry(directory_entry&&) noexcept = default;
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE directory_entry::directory_entry(const filesystem::path & p)
- : _path(p), _file_size(0)
- #ifndef GHC_OS_WINDOWS
- ,
- _hard_link_count(0)
- #endif
- ,
- _last_write_time(0) {
- refresh();
- }
- #endif
- GHC_INLINE directory_entry::directory_entry(const filesystem::path & p,
- std::error_code & ec)
- : _path(p), _file_size(0)
- #ifndef GHC_OS_WINDOWS
- ,
- _hard_link_count(0)
- #endif
- ,
- _last_write_time(0) {
- refresh(ec);
- }
- GHC_INLINE directory_entry::~directory_entry() {}
- // assignments:
- // directory_entry& directory_entry::operator=(const directory_entry&) =
- // default; directory_entry& directory_entry::operator=(directory_entry&&)
- // noexcept = default;
- // 30.10.12.2 directory_entry modifiers
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void directory_entry::assign(const filesystem::path & p) {
- _path = p;
- refresh();
- }
- #endif
- GHC_INLINE void directory_entry::assign(const filesystem::path & p,
- std::error_code & ec) {
- _path = p;
- refresh(ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void
- directory_entry::replace_filename(const filesystem::path & p) {
- _path.replace_filename(p);
- refresh();
- }
- #endif
- GHC_INLINE void
- directory_entry::replace_filename(const filesystem::path & p,
- std::error_code & ec) {
- _path.replace_filename(p);
- refresh(ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void directory_entry::refresh() {
- std::error_code ec;
- refresh(ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
- }
- }
- #endif
- GHC_INLINE void directory_entry::refresh(std::error_code & ec) noexcept {
- #ifdef GHC_OS_WINDOWS
- _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size,
- nullptr, &_last_write_time);
- #else
- _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size,
- &_hard_link_count, &_last_write_time);
- #endif
- }
- // 30.10.12.3 directory_entry observers
- GHC_INLINE const filesystem::path & directory_entry::path() const noexcept {
- return _path;
- }
- GHC_INLINE
- directory_entry::operator const filesystem::path &() const noexcept {
- return _path;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::exists() const {
- return filesystem::exists(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::exists(std::error_code & ec) const noexcept {
- return filesystem::exists(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_block_file() const {
- return filesystem::is_block_file(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_block_file(std::error_code & ec) const noexcept {
- return filesystem::is_block_file(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_character_file() const {
- return filesystem::is_character_file(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_character_file(std::error_code & ec) const noexcept {
- return filesystem::is_character_file(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_directory() const {
- return filesystem::is_directory(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_directory(std::error_code & ec) const noexcept {
- return filesystem::is_directory(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_fifo() const {
- return filesystem::is_fifo(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_fifo(std::error_code & ec) const noexcept {
- return filesystem::is_fifo(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_other() const {
- return filesystem::is_other(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_other(std::error_code & ec) const noexcept {
- return filesystem::is_other(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_regular_file() const {
- return filesystem::is_regular_file(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_regular_file(std::error_code & ec) const noexcept {
- return filesystem::is_regular_file(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_socket() const {
- return filesystem::is_socket(status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_socket(std::error_code & ec) const noexcept {
- return filesystem::is_socket(status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE bool directory_entry::is_symlink() const {
- return filesystem::is_symlink(symlink_status());
- }
- #endif
- GHC_INLINE bool
- directory_entry::is_symlink(std::error_code & ec) const noexcept {
- return filesystem::is_symlink(symlink_status(ec));
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE uintmax_t directory_entry::file_size() const {
- if (_status.type() != file_type::none) { return _file_size; }
- return filesystem::file_size(path());
- }
- #endif
- GHC_INLINE uintmax_t
- directory_entry::file_size(std::error_code & ec) const noexcept {
- if (_status.type() != file_type::none) {
- ec.clear();
- return _file_size;
- }
- return filesystem::file_size(path(), ec);
- }
- #ifndef GHC_OS_WEB
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE uintmax_t directory_entry::hard_link_count() const {
- #ifndef GHC_OS_WINDOWS
- if (_status.type() != file_type::none) { return _hard_link_count; }
- #endif
- return filesystem::hard_link_count(path());
- }
- #endif
- GHC_INLINE uintmax_t
- directory_entry::hard_link_count(std::error_code & ec) const noexcept {
- #ifndef GHC_OS_WINDOWS
- if (_status.type() != file_type::none) {
- ec.clear();
- return _hard_link_count;
- }
- #endif
- return filesystem::hard_link_count(path(), ec);
- }
- #endif
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE file_time_type directory_entry::last_write_time() const {
- if (_status.type() != file_type::none) {
- return std::chrono::system_clock::from_time_t(_last_write_time);
- }
- return filesystem::last_write_time(path());
- }
- #endif
- GHC_INLINE file_time_type
- directory_entry::last_write_time(std::error_code & ec) const noexcept {
- if (_status.type() != file_type::none) {
- ec.clear();
- return std::chrono::system_clock::from_time_t(_last_write_time);
- }
- return filesystem::last_write_time(path(), ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE file_status directory_entry::status() const {
- if (_status.type() != file_type::none) { return _status; }
- return filesystem::status(path());
- }
- #endif
- GHC_INLINE file_status
- directory_entry::status(std::error_code & ec) const noexcept {
- if (_status.type() != file_type::none) {
- ec.clear();
- return _status;
- }
- return filesystem::status(path(), ec);
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE file_status directory_entry::symlink_status() const {
- if (_symlink_status.type() != file_type::none) { return _symlink_status; }
- return filesystem::symlink_status(path());
- }
- #endif
- GHC_INLINE file_status
- directory_entry::symlink_status(std::error_code & ec) const noexcept {
- if (_symlink_status.type() != file_type::none) {
- ec.clear();
- return _symlink_status;
- }
- return filesystem::symlink_status(path(), ec);
- }
- GHC_INLINE bool
- directory_entry::operator<(const directory_entry & rhs) const noexcept {
- return _path < rhs._path;
- }
- GHC_INLINE bool
- directory_entry::operator==(const directory_entry & rhs) const noexcept {
- return _path == rhs._path;
- }
- GHC_INLINE bool
- directory_entry::operator!=(const directory_entry & rhs) const noexcept {
- return _path != rhs._path;
- }
- GHC_INLINE bool
- directory_entry::operator<=(const directory_entry & rhs) const noexcept {
- return _path <= rhs._path;
- }
- GHC_INLINE bool
- directory_entry::operator>(const directory_entry & rhs) const noexcept {
- return _path > rhs._path;
- }
- GHC_INLINE bool
- directory_entry::operator>=(const directory_entry & rhs) const noexcept {
- return _path >= rhs._path;
- }
- //-----------------------------------------------------------------------------
- // 30.10.13 class directory_iterator
- #ifdef GHC_OS_WINDOWS
- class directory_iterator::impl {
- public:
- impl(const path & p, directory_options options)
- : _base(p), _options(options), _dirHandle(INVALID_HANDLE_VALUE) {
- if (!_base.empty()) {
- ZeroMemory(&_findData, sizeof(WIN32_FIND_DATAW));
- if ((_dirHandle = FindFirstFileW(
- detail::fromUtf8<std::wstring>((_base / "*").u8string())
- .c_str(),
- &_findData)) != INVALID_HANDLE_VALUE) {
- if (std::wstring(_findData.cFileName) == L"." ||
- std::wstring(_findData.cFileName) == L"..") {
- increment(_ec);
- } else {
- _current = _base / std::wstring(_findData.cFileName);
- copyToDirEntry(_ec);
- }
- } else {
- auto error = ::GetLastError();
- _base = filesystem::path();
- if (error != ERROR_ACCESS_DENIED ||
- (options & directory_options::skip_permission_denied) ==
- directory_options::none) {
- _ec = detail::make_system_error();
- }
- }
- }
- }
- impl(const impl & other) = delete;
- ~impl() {
- if (_dirHandle != INVALID_HANDLE_VALUE) {
- FindClose(_dirHandle);
- _dirHandle = INVALID_HANDLE_VALUE;
- }
- }
- void increment(std::error_code & ec) {
- if (_dirHandle != INVALID_HANDLE_VALUE) {
- do {
- if (FindNextFileW(_dirHandle, &_findData)) {
- _current = _base;
- #ifdef GHC_RAISE_UNICODE_ERRORS
- try {
- _current.append_name(
- detail::toUtf8(_findData.cFileName).c_str());
- } catch (filesystem_error & fe) {
- ec = fe.code();
- return;
- }
- #else
- _current.append_name(detail::toUtf8(_findData.cFileName).c_str());
- #endif
- copyToDirEntry(ec);
- } else {
- auto err = ::GetLastError();
- if (err != ERROR_NO_MORE_FILES) {
- _ec = ec = detail::make_system_error(err);
- }
- FindClose(_dirHandle);
- _dirHandle = INVALID_HANDLE_VALUE;
- _current = filesystem::path();
- break;
- }
- } while (std::wstring(_findData.cFileName) == L"." ||
- std::wstring(_findData.cFileName) == L"..");
- } else {
- ec = _ec;
- }
- }
- void copyToDirEntry(std::error_code & ec) {
- _dir_entry._path = _current;
- if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- _dir_entry._status = detail::status_ex(
- _current, ec, &_dir_entry._symlink_status, &_dir_entry._file_size,
- nullptr, &_dir_entry._last_write_time);
- } else {
- _dir_entry._status = detail::status_from_INFO(
- _current, &_findData, ec, &_dir_entry._file_size,
- &_dir_entry._last_write_time);
- _dir_entry._symlink_status = _dir_entry._status;
- }
- if (ec) {
- if (_dir_entry._status.type() != file_type::none &&
- _dir_entry._symlink_status.type() != file_type::none) {
- ec.clear();
- } else {
- _dir_entry._file_size = static_cast<uintmax_t>(-1);
- _dir_entry._last_write_time = 0;
- }
- }
- }
- path _base;
- directory_options _options;
- WIN32_FIND_DATAW _findData;
- HANDLE _dirHandle;
- path _current;
- directory_entry _dir_entry;
- std::error_code _ec;
- };
- #else
- // POSIX implementation
- class directory_iterator::impl {
- public:
- impl(const path & path, directory_options options)
- : _base(path), _options(options), _dir(nullptr), _entry(nullptr) {
- if (!path.empty()) { _dir = ::opendir(path.native().c_str()); }
- if (!path.empty()) {
- if (!_dir) {
- auto error = errno;
- _base = filesystem::path();
- if (error != EACCES ||
- (options & directory_options::skip_permission_denied) ==
- directory_options::none) {
- _ec = detail::make_system_error();
- }
- } else {
- increment(_ec);
- }
- }
- }
- impl(const impl & other) = delete;
- ~impl() {
- if (_dir) { ::closedir(_dir); }
- }
- void increment(std::error_code & ec) {
- if (_dir) {
- bool skip;
- do {
- skip = false;
- errno = 0;
- _entry = ::readdir(_dir);
- if (_entry) {
- _current = _base;
- _current.append_name(_entry->d_name);
- _dir_entry = directory_entry(_current, ec);
- if (ec && (ec.value() == EACCES || ec.value() == EPERM) &&
- (_options & directory_options::skip_permission_denied) ==
- directory_options::skip_permission_denied) {
- ec.clear();
- skip = true;
- }
- } else {
- ::closedir(_dir);
- _dir = nullptr;
- _current = path();
- if (errno) { ec = detail::make_system_error(); }
- break;
- }
- } while (skip || std::strcmp(_entry->d_name, ".") == 0 ||
- std::strcmp(_entry->d_name, "..") == 0);
- }
- }
- path _base;
- directory_options _options;
- path _current;
- DIR * _dir;
- struct ::dirent * _entry;
- directory_entry _dir_entry;
- std::error_code _ec;
- };
- #endif
- // 30.10.13.1 member functions
- GHC_INLINE directory_iterator::directory_iterator() noexcept
- : _impl(new impl(path(), directory_options::none)) {}
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE directory_iterator::directory_iterator(const path & p)
- : _impl(new impl(p, directory_options::none)) {
- if (_impl->_ec) {
- throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p,
- _impl->_ec);
- }
- _impl->_ec.clear();
- }
- GHC_INLINE directory_iterator::directory_iterator(const path & p,
- directory_options options)
- : _impl(new impl(p, options)) {
- if (_impl->_ec) {
- throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p,
- _impl->_ec);
- }
- }
- #endif
- GHC_INLINE
- directory_iterator::directory_iterator(const path & p,
- std::error_code & ec) noexcept
- : _impl(new impl(p, directory_options::none)) {
- if (_impl->_ec) { ec = _impl->_ec; }
- }
- GHC_INLINE
- directory_iterator::directory_iterator(const path & p,
- directory_options options,
- std::error_code & ec) noexcept
- : _impl(new impl(p, options)) {
- if (_impl->_ec) { ec = _impl->_ec; }
- }
- GHC_INLINE
- directory_iterator::directory_iterator(const directory_iterator & rhs)
- : _impl(rhs._impl) {}
- GHC_INLINE
- directory_iterator::directory_iterator(directory_iterator && rhs) noexcept
- : _impl(std::move(rhs._impl)) {}
- GHC_INLINE directory_iterator::~directory_iterator() {}
- GHC_INLINE directory_iterator &
- directory_iterator::operator=(const directory_iterator & rhs) {
- _impl = rhs._impl;
- return *this;
- }
- GHC_INLINE directory_iterator &
- directory_iterator::operator=(directory_iterator && rhs) noexcept {
- _impl = std::move(rhs._impl);
- return *this;
- }
- GHC_INLINE const directory_entry & directory_iterator::operator*() const {
- return _impl->_dir_entry;
- }
- GHC_INLINE const directory_entry * directory_iterator::operator->() const {
- return &_impl->_dir_entry;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE directory_iterator & directory_iterator::operator++() {
- std::error_code ec;
- _impl->increment(ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()),
- _impl->_current, ec);
- }
- return *this;
- }
- #endif
- GHC_INLINE directory_iterator &
- directory_iterator::increment(std::error_code & ec) noexcept {
- _impl->increment(ec);
- return *this;
- }
- GHC_INLINE bool
- directory_iterator::operator==(const directory_iterator & rhs) const {
- return _impl->_current == rhs._impl->_current;
- }
- GHC_INLINE bool
- directory_iterator::operator!=(const directory_iterator & rhs) const {
- return _impl->_current != rhs._impl->_current;
- }
- // 30.10.13.2 directory_iterator non-member functions
- GHC_INLINE directory_iterator begin(directory_iterator iter) noexcept {
- return iter;
- }
- GHC_INLINE directory_iterator end(const directory_iterator &) noexcept {
- return directory_iterator();
- }
- //-----------------------------------------------------------------------------
- // 30.10.14 class recursive_directory_iterator
- GHC_INLINE
- recursive_directory_iterator::recursive_directory_iterator() noexcept
- : _impl(new recursive_directory_iterator_impl(directory_options::none,
- true)) {
- _impl->_dir_iter_stack.push(directory_iterator());
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE
- recursive_directory_iterator::recursive_directory_iterator(const path & p)
- : _impl(new recursive_directory_iterator_impl(directory_options::none,
- true)) {
- _impl->_dir_iter_stack.push(directory_iterator(p));
- }
- GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
- const path & p, directory_options options)
- : _impl(new recursive_directory_iterator_impl(options, true)) {
- _impl->_dir_iter_stack.push(directory_iterator(p, options));
- }
- #endif
- GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
- const path & p, directory_options options,
- std::error_code & ec) noexcept
- : _impl(new recursive_directory_iterator_impl(options, true)) {
- _impl->_dir_iter_stack.push(directory_iterator(p, options, ec));
- }
- GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
- const path & p, std::error_code & ec) noexcept
- : _impl(new recursive_directory_iterator_impl(directory_options::none,
- true)) {
- _impl->_dir_iter_stack.push(directory_iterator(p, ec));
- }
- GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
- const recursive_directory_iterator & rhs)
- : _impl(rhs._impl) {}
- GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
- recursive_directory_iterator && rhs) noexcept
- : _impl(std::move(rhs._impl)) {}
- GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {}
- // 30.10.14.1 observers
- GHC_INLINE directory_options recursive_directory_iterator::options() const {
- return _impl->_options;
- }
- GHC_INLINE int recursive_directory_iterator::depth() const {
- return static_cast<int>(_impl->_dir_iter_stack.size() - 1);
- }
- GHC_INLINE bool recursive_directory_iterator::recursion_pending() const {
- return _impl->_recursion_pending;
- }
- GHC_INLINE const directory_entry &
- recursive_directory_iterator::operator*() const {
- return *(_impl->_dir_iter_stack.top());
- }
- GHC_INLINE const directory_entry *
- recursive_directory_iterator::operator->() const {
- return &(*(_impl->_dir_iter_stack.top()));
- }
- // 30.10.14.1 modifiers recursive_directory_iterator&
- GHC_INLINE recursive_directory_iterator &
- recursive_directory_iterator::operator=(
- const recursive_directory_iterator & rhs) {
- _impl = rhs._impl;
- return *this;
- }
- GHC_INLINE recursive_directory_iterator &
- recursive_directory_iterator::operator=(
- recursive_directory_iterator && rhs) noexcept {
- _impl = std::move(rhs._impl);
- return *this;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE recursive_directory_iterator &
- recursive_directory_iterator::operator++() {
- std::error_code ec;
- increment(ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()),
- _impl->_dir_iter_stack.empty()
- ? path()
- : _impl->_dir_iter_stack.top()->path(),
- ec);
- }
- return *this;
- }
- #endif
- GHC_INLINE recursive_directory_iterator &
- recursive_directory_iterator::increment(std::error_code & ec) noexcept {
- auto status = (*this)->status(ec);
- if (ec) return *this;
- auto symlink_status = (*this)->symlink_status(ec);
- if (ec) return *this;
- if (recursion_pending() && is_directory(status) &&
- (!is_symlink(symlink_status) ||
- (options() & directory_options::follow_directory_symlink) !=
- directory_options::none)) {
- _impl->_dir_iter_stack.push(
- directory_iterator((*this)->path(), _impl->_options, ec));
- } else {
- _impl->_dir_iter_stack.top().increment(ec);
- }
- if (!ec) {
- while (depth() &&
- _impl->_dir_iter_stack.top() == directory_iterator()) {
- _impl->_dir_iter_stack.pop();
- _impl->_dir_iter_stack.top().increment(ec);
- }
- } else if (!_impl->_dir_iter_stack.empty()) {
- _impl->_dir_iter_stack.pop();
- }
- _impl->_recursion_pending = true;
- return *this;
- }
- #ifdef GHC_WITH_EXCEPTIONS
- GHC_INLINE void recursive_directory_iterator::pop() {
- std::error_code ec;
- pop(ec);
- if (ec) {
- throw filesystem_error(detail::systemErrorText(ec.value()),
- _impl->_dir_iter_stack.empty()
- ? path()
- : _impl->_dir_iter_stack.top()->path(),
- ec);
- }
- }
- #endif
- GHC_INLINE void recursive_directory_iterator::pop(std::error_code & ec) {
- if (depth() == 0) {
- *this = recursive_directory_iterator();
- } else {
- do {
- _impl->_dir_iter_stack.pop();
- _impl->_dir_iter_stack.top().increment(ec);
- } while (depth() &&
- _impl->_dir_iter_stack.top() == directory_iterator());
- }
- }
- GHC_INLINE void recursive_directory_iterator::disable_recursion_pending() {
- _impl->_recursion_pending = false;
- }
- // other members as required by 27.2.3, input iterators
- GHC_INLINE bool recursive_directory_iterator::operator==(
- const recursive_directory_iterator & rhs) const {
- return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top();
- }
- GHC_INLINE bool recursive_directory_iterator::operator!=(
- const recursive_directory_iterator & rhs) const {
- return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top();
- }
- // 30.10.14.2 directory_iterator non-member functions
- GHC_INLINE recursive_directory_iterator
- begin(recursive_directory_iterator iter) noexcept {
- return iter;
- }
- GHC_INLINE recursive_directory_iterator
- end(const recursive_directory_iterator &) noexcept {
- return recursive_directory_iterator();
- }
- #endif // GHC_EXPAND_IMPL
- } // namespace filesystem
- } // namespace ghc
- // cleanup some macros
- #undef GHC_INLINE
- #undef GHC_EXPAND_IMPL
- #endif // GHC_FILESYSTEM_H
|