inja.hpp 127 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166
  1. // Copyright (c) 2020 Pantor. All rights reserved.
  2. #ifndef INCLUDE_INJA_INJA_HPP_
  3. #define INCLUDE_INJA_INJA_HPP_
  4. #include <nlohmann/json.hpp>
  5. // #include "environment.hpp"
  6. // Copyright (c) 2019 Pantor. All rights reserved.
  7. #ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
  8. #define INCLUDE_INJA_ENVIRONMENT_HPP_
  9. #include <fstream>
  10. #include <iostream>
  11. #include <memory>
  12. #include <sstream>
  13. #include <string>
  14. #include <nlohmann/json.hpp>
  15. // #include "config.hpp"
  16. // Copyright (c) 2019 Pantor. All rights reserved.
  17. #ifndef INCLUDE_INJA_CONFIG_HPP_
  18. #define INCLUDE_INJA_CONFIG_HPP_
  19. #include <functional>
  20. #include <string>
  21. // #include "string_view.hpp"
  22. // Copyright 2017-2019 by Martin Moene
  23. //
  24. // string-view lite, a C++17-like string_view for C++98 and later.
  25. // For more information see https://github.com/martinmoene/string-view-lite
  26. //
  27. // Distributed under the Boost Software License, Version 1.0.
  28. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  29. #ifndef NONSTD_SV_LITE_H_INCLUDED
  30. #define NONSTD_SV_LITE_H_INCLUDED
  31. #define string_view_lite_MAJOR 1
  32. #define string_view_lite_MINOR 4
  33. #define string_view_lite_PATCH 0
  34. #define string_view_lite_VERSION \
  35. nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY( \
  36. string_view_lite_PATCH)
  37. #define nssv_STRINGIFY(x) nssv_STRINGIFY_(x)
  38. #define nssv_STRINGIFY_(x) #x
  39. // string-view lite configuration:
  40. #define nssv_STRING_VIEW_DEFAULT 0
  41. #define nssv_STRING_VIEW_NONSTD 1
  42. #define nssv_STRING_VIEW_STD 2
  43. #if !defined(nssv_CONFIG_SELECT_STRING_VIEW)
  44. #define nssv_CONFIG_SELECT_STRING_VIEW (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD)
  45. #endif
  46. #if defined(nssv_CONFIG_SELECT_STD_STRING_VIEW) || defined(nssv_CONFIG_SELECT_NONSTD_STRING_VIEW)
  47. #error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_...
  48. #endif
  49. #ifndef nssv_CONFIG_STD_SV_OPERATOR
  50. #define nssv_CONFIG_STD_SV_OPERATOR 0
  51. #endif
  52. #ifndef nssv_CONFIG_USR_SV_OPERATOR
  53. #define nssv_CONFIG_USR_SV_OPERATOR 1
  54. #endif
  55. #ifdef nssv_CONFIG_CONVERSION_STD_STRING
  56. #define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
  57. #define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
  58. #endif
  59. #ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
  60. #define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
  61. #endif
  62. #ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  63. #define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
  64. #endif
  65. // Control presence of exception handling (try and auto discover):
  66. #ifndef nssv_CONFIG_NO_EXCEPTIONS
  67. #if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
  68. #define nssv_CONFIG_NO_EXCEPTIONS 0
  69. #else
  70. #define nssv_CONFIG_NO_EXCEPTIONS 1
  71. #endif
  72. #endif
  73. // C++ language version detection (C++20 is speculative):
  74. // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
  75. #ifndef nssv_CPLUSPLUS
  76. #if defined(_MSVC_LANG) && !defined(__clang__)
  77. #define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
  78. #else
  79. #define nssv_CPLUSPLUS __cplusplus
  80. #endif
  81. #endif
  82. #define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L)
  83. #define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L)
  84. #define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L)
  85. #define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L)
  86. #define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L)
  87. #define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202000L)
  88. // use C++17 std::string_view if available and requested:
  89. #if nssv_CPP17_OR_GREATER && defined(__has_include)
  90. #if __has_include(<string_view> )
  91. #define nssv_HAVE_STD_STRING_VIEW 1
  92. #else
  93. #define nssv_HAVE_STD_STRING_VIEW 0
  94. #endif
  95. #else
  96. #define nssv_HAVE_STD_STRING_VIEW 0
  97. #endif
  98. #define nssv_USES_STD_STRING_VIEW \
  99. ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \
  100. ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW))
  101. #define nssv_HAVE_STARTS_WITH (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW)
  102. #define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
  103. //
  104. // Use C++17 std::string_view:
  105. //
  106. #if nssv_USES_STD_STRING_VIEW
  107. #include <string_view>
  108. // Extensions for std::string:
  109. #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  110. namespace nonstd {
  111. template <class CharT, class Traits, class Allocator = std::allocator<CharT>>
  112. std::basic_string<CharT, Traits, Allocator> to_string(std::basic_string_view<CharT, Traits> v,
  113. Allocator const &a = Allocator()) {
  114. return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
  115. }
  116. template <class CharT, class Traits, class Allocator>
  117. std::basic_string_view<CharT, Traits> to_string_view(std::basic_string<CharT, Traits, Allocator> const &s) {
  118. return std::basic_string_view<CharT, Traits>(s.data(), s.size());
  119. }
  120. // Literal operators sv and _sv:
  121. #if nssv_CONFIG_STD_SV_OPERATOR
  122. using namespace std::literals::string_view_literals;
  123. #endif
  124. #if nssv_CONFIG_USR_SV_OPERATOR
  125. inline namespace literals {
  126. inline namespace string_view_literals {
  127. constexpr std::string_view operator"" _sv(const char *str, size_t len) noexcept // (1)
  128. {
  129. return std::string_view {str, len};
  130. }
  131. constexpr std::u16string_view operator"" _sv(const char16_t *str, size_t len) noexcept // (2)
  132. {
  133. return std::u16string_view {str, len};
  134. }
  135. constexpr std::u32string_view operator"" _sv(const char32_t *str, size_t len) noexcept // (3)
  136. {
  137. return std::u32string_view {str, len};
  138. }
  139. constexpr std::wstring_view operator"" _sv(const wchar_t *str, size_t len) noexcept // (4)
  140. {
  141. return std::wstring_view {str, len};
  142. }
  143. } // namespace string_view_literals
  144. } // namespace literals
  145. #endif // nssv_CONFIG_USR_SV_OPERATOR
  146. } // namespace nonstd
  147. #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  148. namespace nonstd {
  149. using std::basic_string_view;
  150. using std::string_view;
  151. using std::u16string_view;
  152. using std::u32string_view;
  153. using std::wstring_view;
  154. // literal "sv" and "_sv", see above
  155. using std::operator==;
  156. using std::operator!=;
  157. using std::operator<;
  158. using std::operator<=;
  159. using std::operator>;
  160. using std::operator>=;
  161. using std::operator<<;
  162. } // namespace nonstd
  163. #else // nssv_HAVE_STD_STRING_VIEW
  164. //
  165. // Before C++17: use string_view lite:
  166. //
  167. // Compiler versions:
  168. //
  169. // MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
  170. // MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
  171. // MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
  172. // MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
  173. // MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
  174. // MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
  175. // MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
  176. // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
  177. // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
  178. // MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
  179. #if defined(_MSC_VER) && !defined(__clang__)
  180. #define nssv_COMPILER_MSVC_VER (_MSC_VER)
  181. #define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
  182. #else
  183. #define nssv_COMPILER_MSVC_VER 0
  184. #define nssv_COMPILER_MSVC_VERSION 0
  185. #endif
  186. #define nssv_COMPILER_VERSION(major, minor, patch) (10 * (10 * (major) + (minor)) + (patch))
  187. #if defined(__clang__)
  188. #define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
  189. #else
  190. #define nssv_COMPILER_CLANG_VERSION 0
  191. #endif
  192. #if defined(__GNUC__) && !defined(__clang__)
  193. #define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
  194. #else
  195. #define nssv_COMPILER_GNUC_VERSION 0
  196. #endif
  197. // half-open range [lo..hi):
  198. #define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
  199. // Presence of language and library features:
  200. #ifdef _HAS_CPP0X
  201. #define nssv_HAS_CPP0X _HAS_CPP0X
  202. #else
  203. #define nssv_HAS_CPP0X 0
  204. #endif
  205. // Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
  206. #if nssv_COMPILER_MSVC_VER >= 1900
  207. #undef nssv_CPP11_OR_GREATER
  208. #define nssv_CPP11_OR_GREATER 1
  209. #endif
  210. #define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
  211. #define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
  212. #define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
  213. #define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
  214. #define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
  215. #define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
  216. #define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
  217. #define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
  218. // Presence of C++11 language features:
  219. #define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
  220. #define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
  221. #define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
  222. #define nssv_HAVE_NOEXCEPT nssv_CPP11_140
  223. #define nssv_HAVE_NULLPTR nssv_CPP11_100
  224. #define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
  225. #define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
  226. #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
  227. #define nssv_HAVE_WCHAR16_T nssv_CPP11_100
  228. #define nssv_HAVE_WCHAR32_T nssv_CPP11_100
  229. #if !((nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION) || nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400))
  230. #define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
  231. #else
  232. #define nssv_HAVE_STD_DEFINED_LITERALS 0
  233. #endif
  234. // Presence of C++14 language features:
  235. #define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
  236. // Presence of C++17 language features:
  237. #define nssv_HAVE_NODISCARD nssv_CPP17_000
  238. // Presence of C++ library features:
  239. #define nssv_HAVE_STD_HASH nssv_CPP11_120
  240. // C++ feature usage:
  241. #if nssv_HAVE_CONSTEXPR_11
  242. #define nssv_constexpr constexpr
  243. #else
  244. #define nssv_constexpr /*constexpr*/
  245. #endif
  246. #if nssv_HAVE_CONSTEXPR_14
  247. #define nssv_constexpr14 constexpr
  248. #else
  249. #define nssv_constexpr14 /*constexpr*/
  250. #endif
  251. #if nssv_HAVE_EXPLICIT_CONVERSION
  252. #define nssv_explicit explicit
  253. #else
  254. #define nssv_explicit /*explicit*/
  255. #endif
  256. #if nssv_HAVE_INLINE_NAMESPACE
  257. #define nssv_inline_ns inline
  258. #else
  259. #define nssv_inline_ns /*inline*/
  260. #endif
  261. #if nssv_HAVE_NOEXCEPT
  262. #define nssv_noexcept noexcept
  263. #else
  264. #define nssv_noexcept /*noexcept*/
  265. #endif
  266. //#if nssv_HAVE_REF_QUALIFIER
  267. //# define nssv_ref_qual &
  268. //# define nssv_refref_qual &&
  269. //#else
  270. //# define nssv_ref_qual /*&*/
  271. //# define nssv_refref_qual /*&&*/
  272. //#endif
  273. #if nssv_HAVE_NULLPTR
  274. #define nssv_nullptr nullptr
  275. #else
  276. #define nssv_nullptr NULL
  277. #endif
  278. #if nssv_HAVE_NODISCARD
  279. #define nssv_nodiscard [[nodiscard]]
  280. #else
  281. #define nssv_nodiscard /*[[nodiscard]]*/
  282. #endif
  283. // Additional includes:
  284. #include <algorithm>
  285. #include <cassert>
  286. #include <iterator>
  287. #include <limits>
  288. #include <ostream>
  289. #include <string> // std::char_traits<>
  290. #if !nssv_CONFIG_NO_EXCEPTIONS
  291. #include <stdexcept>
  292. #endif
  293. #if nssv_CPP11_OR_GREATER
  294. #include <type_traits>
  295. #endif
  296. // Clang, GNUC, MSVC warning suppression macros:
  297. #if defined(__clang__)
  298. #pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
  299. #pragma clang diagnostic push
  300. #pragma clang diagnostic ignored "-Wuser-defined-literals"
  301. #elif defined(__GNUC__)
  302. #pragma GCC diagnostic push
  303. #pragma GCC diagnostic ignored "-Wliteral-suffix"
  304. #endif // __clang__
  305. #if nssv_COMPILER_MSVC_VERSION >= 140
  306. #define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
  307. #define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress : code))
  308. #define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable : codes))
  309. #else
  310. #define nssv_SUPPRESS_MSGSL_WARNING(expr)
  311. #define nssv_SUPPRESS_MSVC_WARNING(code, descr)
  312. #define nssv_DISABLE_MSVC_WARNINGS(codes)
  313. #endif
  314. #if defined(__clang__)
  315. #define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
  316. #elif defined(__GNUC__)
  317. #define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
  318. #elif nssv_COMPILER_MSVC_VERSION >= 140
  319. #define nssv_RESTORE_WARNINGS() __pragma(warning(pop))
  320. #else
  321. #define nssv_RESTORE_WARNINGS()
  322. #endif
  323. // Suppress the following MSVC (GSL) warnings:
  324. // - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
  325. // start with an underscore are reserved
  326. // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
  327. // use brace initialization, gsl::narrow_cast or gsl::narow
  328. // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
  329. nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472)
  330. // nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
  331. // nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
  332. namespace nonstd {
  333. namespace sv_lite {
  334. #if nssv_CPP11_OR_GREATER
  335. namespace detail {
  336. // Expect tail call optimization to make length() non-recursive:
  337. template <typename CharT> inline constexpr std::size_t length(CharT *s, std::size_t result = 0) {
  338. return *s == '\0' ? result : length(s + 1, result + 1);
  339. }
  340. } // namespace detail
  341. #endif // nssv_CPP11_OR_GREATER
  342. template <class CharT, class Traits = std::char_traits<CharT>> class basic_string_view;
  343. //
  344. // basic_string_view:
  345. //
  346. template <class CharT, class Traits /* = std::char_traits<CharT> */
  347. >
  348. class basic_string_view {
  349. public:
  350. // Member types:
  351. typedef Traits traits_type;
  352. typedef CharT value_type;
  353. typedef CharT *pointer;
  354. typedef CharT const *const_pointer;
  355. typedef CharT &reference;
  356. typedef CharT const &const_reference;
  357. typedef const_pointer iterator;
  358. typedef const_pointer const_iterator;
  359. typedef std::reverse_iterator<const_iterator> reverse_iterator;
  360. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  361. typedef std::size_t size_type;
  362. typedef std::ptrdiff_t difference_type;
  363. // 24.4.2.1 Construction and assignment:
  364. nssv_constexpr basic_string_view() nssv_noexcept : data_(nssv_nullptr), size_(0) {}
  365. #if nssv_CPP11_OR_GREATER
  366. nssv_constexpr basic_string_view(basic_string_view const &other) nssv_noexcept = default;
  367. #else
  368. nssv_constexpr basic_string_view(basic_string_view const &other) nssv_noexcept : data_(other.data_),
  369. size_(other.size_) {}
  370. #endif
  371. nssv_constexpr basic_string_view(CharT const *s, size_type count) nssv_noexcept // non-standard noexcept
  372. : data_(s),
  373. size_(count) {}
  374. nssv_constexpr basic_string_view(CharT const *s) nssv_noexcept // non-standard noexcept
  375. : data_(s)
  376. #if nssv_CPP17_OR_GREATER
  377. ,
  378. size_(Traits::length(s))
  379. #elif nssv_CPP11_OR_GREATER
  380. ,
  381. size_(detail::length(s))
  382. #else
  383. ,
  384. size_(Traits::length(s))
  385. #endif
  386. {
  387. }
  388. // Assignment:
  389. #if nssv_CPP11_OR_GREATER
  390. nssv_constexpr14 basic_string_view &operator=(basic_string_view const &other) nssv_noexcept = default;
  391. #else
  392. nssv_constexpr14 basic_string_view &operator=(basic_string_view const &other) nssv_noexcept {
  393. data_ = other.data_;
  394. size_ = other.size_;
  395. return *this;
  396. }
  397. #endif
  398. // 24.4.2.2 Iterator support:
  399. nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; }
  400. nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; }
  401. nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
  402. nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); }
  403. nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator(end()); }
  404. nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator(begin()); }
  405. nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
  406. nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); }
  407. // 24.4.2.3 Capacity:
  408. nssv_constexpr size_type size() const nssv_noexcept { return size_; }
  409. nssv_constexpr size_type length() const nssv_noexcept { return size_; }
  410. nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits<size_type>::max)(); }
  411. // since C++20
  412. nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept { return 0 == size_; }
  413. // 24.4.2.4 Element access:
  414. nssv_constexpr const_reference operator[](size_type pos) const { return data_at(pos); }
  415. nssv_constexpr14 const_reference at(size_type pos) const {
  416. #if nssv_CONFIG_NO_EXCEPTIONS
  417. assert(pos < size());
  418. #else
  419. if (pos >= size()) {
  420. throw std::out_of_range("nonstd::string_view::at()");
  421. }
  422. #endif
  423. return data_at(pos);
  424. }
  425. nssv_constexpr const_reference front() const { return data_at(0); }
  426. nssv_constexpr const_reference back() const { return data_at(size() - 1); }
  427. nssv_constexpr const_pointer data() const nssv_noexcept { return data_; }
  428. // 24.4.2.5 Modifiers:
  429. nssv_constexpr14 void remove_prefix(size_type n) {
  430. assert(n <= size());
  431. data_ += n;
  432. size_ -= n;
  433. }
  434. nssv_constexpr14 void remove_suffix(size_type n) {
  435. assert(n <= size());
  436. size_ -= n;
  437. }
  438. nssv_constexpr14 void swap(basic_string_view &other) nssv_noexcept {
  439. using std::swap;
  440. swap(data_, other.data_);
  441. swap(size_, other.size_);
  442. }
  443. // 24.4.2.6 String operations:
  444. size_type copy(CharT *dest, size_type n, size_type pos = 0) const {
  445. #if nssv_CONFIG_NO_EXCEPTIONS
  446. assert(pos <= size());
  447. #else
  448. if (pos > size()) {
  449. throw std::out_of_range("nonstd::string_view::copy()");
  450. }
  451. #endif
  452. const size_type rlen = (std::min)(n, size() - pos);
  453. (void)Traits::copy(dest, data() + pos, rlen);
  454. return rlen;
  455. }
  456. nssv_constexpr14 basic_string_view substr(size_type pos = 0, size_type n = npos) const {
  457. #if nssv_CONFIG_NO_EXCEPTIONS
  458. assert(pos <= size());
  459. #else
  460. if (pos > size()) {
  461. throw std::out_of_range("nonstd::string_view::substr()");
  462. }
  463. #endif
  464. return basic_string_view(data() + pos, (std::min)(n, size() - pos));
  465. }
  466. // compare(), 6x:
  467. nssv_constexpr14 int compare(basic_string_view other) const nssv_noexcept // (1)
  468. {
  469. if (const int result = Traits::compare(data(), other.data(), (std::min)(size(), other.size()))) {
  470. return result;
  471. }
  472. return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
  473. }
  474. nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other) const // (2)
  475. {
  476. return substr(pos1, n1).compare(other);
  477. }
  478. nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other, size_type pos2,
  479. size_type n2) const // (3)
  480. {
  481. return substr(pos1, n1).compare(other.substr(pos2, n2));
  482. }
  483. nssv_constexpr int compare(CharT const *s) const // (4)
  484. {
  485. return compare(basic_string_view(s));
  486. }
  487. nssv_constexpr int compare(size_type pos1, size_type n1, CharT const *s) const // (5)
  488. {
  489. return substr(pos1, n1).compare(basic_string_view(s));
  490. }
  491. nssv_constexpr int compare(size_type pos1, size_type n1, CharT const *s, size_type n2) const // (6)
  492. {
  493. return substr(pos1, n1).compare(basic_string_view(s, n2));
  494. }
  495. // 24.4.2.7 Searching:
  496. // starts_with(), 3x, since C++20:
  497. nssv_constexpr bool starts_with(basic_string_view v) const nssv_noexcept // (1)
  498. {
  499. return size() >= v.size() && compare(0, v.size(), v) == 0;
  500. }
  501. nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2)
  502. {
  503. return starts_with(basic_string_view(&c, 1));
  504. }
  505. nssv_constexpr bool starts_with(CharT const *s) const // (3)
  506. {
  507. return starts_with(basic_string_view(s));
  508. }
  509. // ends_with(), 3x, since C++20:
  510. nssv_constexpr bool ends_with(basic_string_view v) const nssv_noexcept // (1)
  511. {
  512. return size() >= v.size() && compare(size() - v.size(), npos, v) == 0;
  513. }
  514. nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2)
  515. {
  516. return ends_with(basic_string_view(&c, 1));
  517. }
  518. nssv_constexpr bool ends_with(CharT const *s) const // (3)
  519. {
  520. return ends_with(basic_string_view(s));
  521. }
  522. // find(), 4x:
  523. nssv_constexpr14 size_type find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
  524. {
  525. return assert(v.size() == 0 || v.data() != nssv_nullptr),
  526. pos >= size() ? npos : to_pos(std::search(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq));
  527. }
  528. nssv_constexpr14 size_type find(CharT c, size_type pos = 0) const nssv_noexcept // (2)
  529. {
  530. return find(basic_string_view(&c, 1), pos);
  531. }
  532. nssv_constexpr14 size_type find(CharT const *s, size_type pos, size_type n) const // (3)
  533. {
  534. return find(basic_string_view(s, n), pos);
  535. }
  536. nssv_constexpr14 size_type find(CharT const *s, size_type pos = 0) const // (4)
  537. {
  538. return find(basic_string_view(s), pos);
  539. }
  540. // rfind(), 4x:
  541. nssv_constexpr14 size_type rfind(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1)
  542. {
  543. if (size() < v.size()) {
  544. return npos;
  545. }
  546. if (v.empty()) {
  547. return (std::min)(size(), pos);
  548. }
  549. const_iterator last = cbegin() + (std::min)(size() - v.size(), pos) + v.size();
  550. const_iterator result = std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq);
  551. return result != last ? size_type(result - cbegin()) : npos;
  552. }
  553. nssv_constexpr14 size_type rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2)
  554. {
  555. return rfind(basic_string_view(&c, 1), pos);
  556. }
  557. nssv_constexpr14 size_type rfind(CharT const *s, size_type pos, size_type n) const // (3)
  558. {
  559. return rfind(basic_string_view(s, n), pos);
  560. }
  561. nssv_constexpr14 size_type rfind(CharT const *s, size_type pos = npos) const // (4)
  562. {
  563. return rfind(basic_string_view(s), pos);
  564. }
  565. // find_first_of(), 4x:
  566. nssv_constexpr size_type find_first_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
  567. {
  568. return pos >= size() ? npos
  569. : to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq));
  570. }
  571. nssv_constexpr size_type find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2)
  572. {
  573. return find_first_of(basic_string_view(&c, 1), pos);
  574. }
  575. nssv_constexpr size_type find_first_of(CharT const *s, size_type pos, size_type n) const // (3)
  576. {
  577. return find_first_of(basic_string_view(s, n), pos);
  578. }
  579. nssv_constexpr size_type find_first_of(CharT const *s, size_type pos = 0) const // (4)
  580. {
  581. return find_first_of(basic_string_view(s), pos);
  582. }
  583. // find_last_of(), 4x:
  584. nssv_constexpr size_type find_last_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1)
  585. {
  586. return empty() ? npos
  587. : pos >= size() ? find_last_of(v, size() - 1)
  588. : to_pos(std::find_first_of(const_reverse_iterator(cbegin() + pos + 1), crend(),
  589. v.cbegin(), v.cend(), Traits::eq));
  590. }
  591. nssv_constexpr size_type find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2)
  592. {
  593. return find_last_of(basic_string_view(&c, 1), pos);
  594. }
  595. nssv_constexpr size_type find_last_of(CharT const *s, size_type pos, size_type count) const // (3)
  596. {
  597. return find_last_of(basic_string_view(s, count), pos);
  598. }
  599. nssv_constexpr size_type find_last_of(CharT const *s, size_type pos = npos) const // (4)
  600. {
  601. return find_last_of(basic_string_view(s), pos);
  602. }
  603. // find_first_not_of(), 4x:
  604. nssv_constexpr size_type find_first_not_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
  605. {
  606. return pos >= size() ? npos : to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v)));
  607. }
  608. nssv_constexpr size_type find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2)
  609. {
  610. return find_first_not_of(basic_string_view(&c, 1), pos);
  611. }
  612. nssv_constexpr size_type find_first_not_of(CharT const *s, size_type pos, size_type count) const // (3)
  613. {
  614. return find_first_not_of(basic_string_view(s, count), pos);
  615. }
  616. nssv_constexpr size_type find_first_not_of(CharT const *s, size_type pos = 0) const // (4)
  617. {
  618. return find_first_not_of(basic_string_view(s), pos);
  619. }
  620. // find_last_not_of(), 4x:
  621. nssv_constexpr size_type find_last_not_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1)
  622. {
  623. return empty() ? npos
  624. : pos >= size()
  625. ? find_last_not_of(v, size() - 1)
  626. : to_pos(std::find_if(const_reverse_iterator(cbegin() + pos + 1), crend(), not_in_view(v)));
  627. }
  628. nssv_constexpr size_type find_last_not_of(CharT c, size_type pos = npos) const nssv_noexcept // (2)
  629. {
  630. return find_last_not_of(basic_string_view(&c, 1), pos);
  631. }
  632. nssv_constexpr size_type find_last_not_of(CharT const *s, size_type pos, size_type count) const // (3)
  633. {
  634. return find_last_not_of(basic_string_view(s, count), pos);
  635. }
  636. nssv_constexpr size_type find_last_not_of(CharT const *s, size_type pos = npos) const // (4)
  637. {
  638. return find_last_not_of(basic_string_view(s), pos);
  639. }
  640. // Constants:
  641. #if nssv_CPP17_OR_GREATER
  642. static nssv_constexpr size_type npos = size_type(-1);
  643. #elif nssv_CPP11_OR_GREATER
  644. enum : size_type { npos = size_type(-1) };
  645. #else
  646. enum { npos = size_type(-1) };
  647. #endif
  648. private:
  649. struct not_in_view {
  650. const basic_string_view v;
  651. nssv_constexpr explicit not_in_view(basic_string_view v) : v(v) {}
  652. nssv_constexpr bool operator()(CharT c) const { return npos == v.find_first_of(c); }
  653. };
  654. nssv_constexpr size_type to_pos(const_iterator it) const { return it == cend() ? npos : size_type(it - cbegin()); }
  655. nssv_constexpr size_type to_pos(const_reverse_iterator it) const {
  656. return it == crend() ? npos : size_type(crend() - it - 1);
  657. }
  658. nssv_constexpr const_reference data_at(size_type pos) const {
  659. #if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500)
  660. return data_[pos];
  661. #else
  662. return assert(pos < size()), data_[pos];
  663. #endif
  664. }
  665. private:
  666. const_pointer data_;
  667. size_type size_;
  668. public:
  669. #if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
  670. template <class Allocator>
  671. basic_string_view(std::basic_string<CharT, Traits, Allocator> const &s) nssv_noexcept : data_(s.data()),
  672. size_(s.size()) {}
  673. #if nssv_HAVE_EXPLICIT_CONVERSION
  674. template <class Allocator> explicit operator std::basic_string<CharT, Traits, Allocator>() const {
  675. return to_string(Allocator());
  676. }
  677. #endif // nssv_HAVE_EXPLICIT_CONVERSION
  678. #if nssv_CPP11_OR_GREATER
  679. template <class Allocator = std::allocator<CharT>>
  680. std::basic_string<CharT, Traits, Allocator> to_string(Allocator const &a = Allocator()) const {
  681. return std::basic_string<CharT, Traits, Allocator>(begin(), end(), a);
  682. }
  683. #else
  684. std::basic_string<CharT, Traits> to_string() const { return std::basic_string<CharT, Traits>(begin(), end()); }
  685. template <class Allocator> std::basic_string<CharT, Traits, Allocator> to_string(Allocator const &a) const {
  686. return std::basic_string<CharT, Traits, Allocator>(begin(), end(), a);
  687. }
  688. #endif // nssv_CPP11_OR_GREATER
  689. #endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
  690. };
  691. //
  692. // Non-member functions:
  693. //
  694. // 24.4.3 Non-member comparison functions:
  695. // lexicographically compare two string views (function template):
  696. template <class CharT, class Traits>
  697. nssv_constexpr bool operator==(basic_string_view<CharT, Traits> lhs,
  698. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  699. return lhs.compare(rhs) == 0;
  700. }
  701. template <class CharT, class Traits>
  702. nssv_constexpr bool operator!=(basic_string_view<CharT, Traits> lhs,
  703. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  704. return lhs.compare(rhs) != 0;
  705. }
  706. template <class CharT, class Traits>
  707. nssv_constexpr bool operator<(basic_string_view<CharT, Traits> lhs,
  708. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  709. return lhs.compare(rhs) < 0;
  710. }
  711. template <class CharT, class Traits>
  712. nssv_constexpr bool operator<=(basic_string_view<CharT, Traits> lhs,
  713. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  714. return lhs.compare(rhs) <= 0;
  715. }
  716. template <class CharT, class Traits>
  717. nssv_constexpr bool operator>(basic_string_view<CharT, Traits> lhs,
  718. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  719. return lhs.compare(rhs) > 0;
  720. }
  721. template <class CharT, class Traits>
  722. nssv_constexpr bool operator>=(basic_string_view<CharT, Traits> lhs,
  723. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  724. return lhs.compare(rhs) >= 0;
  725. }
  726. // Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
  727. // Implementations shall provide sufficient additional overloads marked
  728. // constexpr and noexcept so that an object t with an implicit conversion
  729. // to S can be compared according to Table 67.
  730. #if !nssv_CPP11_OR_GREATER || nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141)
  731. // accomodate for older compilers:
  732. // ==
  733. template <class CharT, class Traits>
  734. nssv_constexpr bool operator==(basic_string_view<CharT, Traits> lhs, char const *rhs) nssv_noexcept {
  735. return lhs.compare(rhs) == 0;
  736. }
  737. template <class CharT, class Traits>
  738. nssv_constexpr bool operator==(char const *lhs, basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  739. return rhs.compare(lhs) == 0;
  740. }
  741. template <class CharT, class Traits>
  742. nssv_constexpr bool operator==(basic_string_view<CharT, Traits> lhs,
  743. std::basic_string<CharT, Traits> rhs) nssv_noexcept {
  744. return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
  745. }
  746. template <class CharT, class Traits>
  747. nssv_constexpr bool operator==(std::basic_string<CharT, Traits> rhs,
  748. basic_string_view<CharT, Traits> lhs) nssv_noexcept {
  749. return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
  750. }
  751. // !=
  752. template <class CharT, class Traits>
  753. nssv_constexpr bool operator!=(basic_string_view<CharT, Traits> lhs, char const *rhs) nssv_noexcept {
  754. return lhs.compare(rhs) != 0;
  755. }
  756. template <class CharT, class Traits>
  757. nssv_constexpr bool operator!=(char const *lhs, basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  758. return rhs.compare(lhs) != 0;
  759. }
  760. template <class CharT, class Traits>
  761. nssv_constexpr bool operator!=(basic_string_view<CharT, Traits> lhs,
  762. std::basic_string<CharT, Traits> rhs) nssv_noexcept {
  763. return lhs.size() != rhs.size() && lhs.compare(rhs) != 0;
  764. }
  765. template <class CharT, class Traits>
  766. nssv_constexpr bool operator!=(std::basic_string<CharT, Traits> rhs,
  767. basic_string_view<CharT, Traits> lhs) nssv_noexcept {
  768. return lhs.size() != rhs.size() || rhs.compare(lhs) != 0;
  769. }
  770. // <
  771. template <class CharT, class Traits>
  772. nssv_constexpr bool operator<(basic_string_view<CharT, Traits> lhs, char const *rhs) nssv_noexcept {
  773. return lhs.compare(rhs) < 0;
  774. }
  775. template <class CharT, class Traits>
  776. nssv_constexpr bool operator<(char const *lhs, basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  777. return rhs.compare(lhs) > 0;
  778. }
  779. template <class CharT, class Traits>
  780. nssv_constexpr bool operator<(basic_string_view<CharT, Traits> lhs,
  781. std::basic_string<CharT, Traits> rhs) nssv_noexcept {
  782. return lhs.compare(rhs) < 0;
  783. }
  784. template <class CharT, class Traits>
  785. nssv_constexpr bool operator<(std::basic_string<CharT, Traits> rhs,
  786. basic_string_view<CharT, Traits> lhs) nssv_noexcept {
  787. return rhs.compare(lhs) > 0;
  788. }
  789. // <=
  790. template <class CharT, class Traits>
  791. nssv_constexpr bool operator<=(basic_string_view<CharT, Traits> lhs, char const *rhs) nssv_noexcept {
  792. return lhs.compare(rhs) <= 0;
  793. }
  794. template <class CharT, class Traits>
  795. nssv_constexpr bool operator<=(char const *lhs, basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  796. return rhs.compare(lhs) >= 0;
  797. }
  798. template <class CharT, class Traits>
  799. nssv_constexpr bool operator<=(basic_string_view<CharT, Traits> lhs,
  800. std::basic_string<CharT, Traits> rhs) nssv_noexcept {
  801. return lhs.compare(rhs) <= 0;
  802. }
  803. template <class CharT, class Traits>
  804. nssv_constexpr bool operator<=(std::basic_string<CharT, Traits> rhs,
  805. basic_string_view<CharT, Traits> lhs) nssv_noexcept {
  806. return rhs.compare(lhs) >= 0;
  807. }
  808. // >
  809. template <class CharT, class Traits>
  810. nssv_constexpr bool operator>(basic_string_view<CharT, Traits> lhs, char const *rhs) nssv_noexcept {
  811. return lhs.compare(rhs) > 0;
  812. }
  813. template <class CharT, class Traits>
  814. nssv_constexpr bool operator>(char const *lhs, basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  815. return rhs.compare(lhs) < 0;
  816. }
  817. template <class CharT, class Traits>
  818. nssv_constexpr bool operator>(basic_string_view<CharT, Traits> lhs,
  819. std::basic_string<CharT, Traits> rhs) nssv_noexcept {
  820. return lhs.compare(rhs) > 0;
  821. }
  822. template <class CharT, class Traits>
  823. nssv_constexpr bool operator>(std::basic_string<CharT, Traits> rhs,
  824. basic_string_view<CharT, Traits> lhs) nssv_noexcept {
  825. return rhs.compare(lhs) < 0;
  826. }
  827. // >=
  828. template <class CharT, class Traits>
  829. nssv_constexpr bool operator>=(basic_string_view<CharT, Traits> lhs, char const *rhs) nssv_noexcept {
  830. return lhs.compare(rhs) >= 0;
  831. }
  832. template <class CharT, class Traits>
  833. nssv_constexpr bool operator>=(char const *lhs, basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  834. return rhs.compare(lhs) <= 0;
  835. }
  836. template <class CharT, class Traits>
  837. nssv_constexpr bool operator>=(basic_string_view<CharT, Traits> lhs,
  838. std::basic_string<CharT, Traits> rhs) nssv_noexcept {
  839. return lhs.compare(rhs) >= 0;
  840. }
  841. template <class CharT, class Traits>
  842. nssv_constexpr bool operator>=(std::basic_string<CharT, Traits> rhs,
  843. basic_string_view<CharT, Traits> lhs) nssv_noexcept {
  844. return rhs.compare(lhs) <= 0;
  845. }
  846. #else // newer compilers:
  847. #define nssv_BASIC_STRING_VIEW_I(T, U) typename std::decay<basic_string_view<T, U>>::type
  848. #if nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 140, 150)
  849. #define nssv_MSVC_ORDER(x) , int = x
  850. #else
  851. #define nssv_MSVC_ORDER(x) /*, int=x*/
  852. #endif
  853. // ==
  854. template <class CharT, class Traits nssv_MSVC_ORDER(1)>
  855. nssv_constexpr bool operator==(basic_string_view<CharT, Traits> lhs,
  856. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept {
  857. return lhs.compare(rhs) == 0;
  858. }
  859. template <class CharT, class Traits nssv_MSVC_ORDER(2)>
  860. nssv_constexpr bool operator==(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  861. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  862. return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
  863. }
  864. // !=
  865. template <class CharT, class Traits nssv_MSVC_ORDER(1)>
  866. nssv_constexpr bool operator!=(basic_string_view<CharT, Traits> lhs,
  867. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept {
  868. return lhs.size() != rhs.size() || lhs.compare(rhs) != 0;
  869. }
  870. template <class CharT, class Traits nssv_MSVC_ORDER(2)>
  871. nssv_constexpr bool operator!=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  872. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  873. return lhs.compare(rhs) != 0;
  874. }
  875. // <
  876. template <class CharT, class Traits nssv_MSVC_ORDER(1)>
  877. nssv_constexpr bool operator<(basic_string_view<CharT, Traits> lhs,
  878. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept {
  879. return lhs.compare(rhs) < 0;
  880. }
  881. template <class CharT, class Traits nssv_MSVC_ORDER(2)>
  882. nssv_constexpr bool operator<(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  883. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  884. return lhs.compare(rhs) < 0;
  885. }
  886. // <=
  887. template <class CharT, class Traits nssv_MSVC_ORDER(1)>
  888. nssv_constexpr bool operator<=(basic_string_view<CharT, Traits> lhs,
  889. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept {
  890. return lhs.compare(rhs) <= 0;
  891. }
  892. template <class CharT, class Traits nssv_MSVC_ORDER(2)>
  893. nssv_constexpr bool operator<=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  894. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  895. return lhs.compare(rhs) <= 0;
  896. }
  897. // >
  898. template <class CharT, class Traits nssv_MSVC_ORDER(1)>
  899. nssv_constexpr bool operator>(basic_string_view<CharT, Traits> lhs,
  900. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept {
  901. return lhs.compare(rhs) > 0;
  902. }
  903. template <class CharT, class Traits nssv_MSVC_ORDER(2)>
  904. nssv_constexpr bool operator>(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  905. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  906. return lhs.compare(rhs) > 0;
  907. }
  908. // >=
  909. template <class CharT, class Traits nssv_MSVC_ORDER(1)>
  910. nssv_constexpr bool operator>=(basic_string_view<CharT, Traits> lhs,
  911. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept {
  912. return lhs.compare(rhs) >= 0;
  913. }
  914. template <class CharT, class Traits nssv_MSVC_ORDER(2)>
  915. nssv_constexpr bool operator>=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  916. basic_string_view<CharT, Traits> rhs) nssv_noexcept {
  917. return lhs.compare(rhs) >= 0;
  918. }
  919. #undef nssv_MSVC_ORDER
  920. #undef nssv_BASIC_STRING_VIEW_I
  921. #endif // compiler-dependent approach to comparisons
  922. // 24.4.4 Inserters and extractors:
  923. namespace detail {
  924. template <class Stream> void write_padding(Stream &os, std::streamsize n) {
  925. for (std::streamsize i = 0; i < n; ++i)
  926. os.rdbuf()->sputc(os.fill());
  927. }
  928. template <class Stream, class View> Stream &write_to_stream(Stream &os, View const &sv) {
  929. typename Stream::sentry sentry(os);
  930. if (!os)
  931. return os;
  932. const std::streamsize length = static_cast<std::streamsize>(sv.length());
  933. // Whether, and how, to pad:
  934. const bool pad = (length < os.width());
  935. const bool left_pad = pad && (os.flags() & std::ios_base::adjustfield) == std::ios_base::right;
  936. if (left_pad)
  937. write_padding(os, os.width() - length);
  938. // Write span characters:
  939. os.rdbuf()->sputn(sv.begin(), length);
  940. if (pad && !left_pad)
  941. write_padding(os, os.width() - length);
  942. // Reset output stream width:
  943. os.width(0);
  944. return os;
  945. }
  946. } // namespace detail
  947. template <class CharT, class Traits>
  948. std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os,
  949. basic_string_view<CharT, Traits> sv) {
  950. return detail::write_to_stream(os, sv);
  951. }
  952. // Several typedefs for common character types are provided:
  953. typedef basic_string_view<char> string_view;
  954. typedef basic_string_view<wchar_t> wstring_view;
  955. #if nssv_HAVE_WCHAR16_T
  956. typedef basic_string_view<char16_t> u16string_view;
  957. typedef basic_string_view<char32_t> u32string_view;
  958. #endif
  959. } // namespace sv_lite
  960. } // namespace nonstd::sv_lite
  961. //
  962. // 24.4.6 Suffix for basic_string_view literals:
  963. //
  964. #if nssv_HAVE_USER_DEFINED_LITERALS
  965. namespace nonstd {
  966. nssv_inline_ns namespace literals {
  967. nssv_inline_ns namespace string_view_literals {
  968. #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
  969. nssv_constexpr nonstd::sv_lite::string_view operator"" sv(const char *str, size_t len) nssv_noexcept // (1)
  970. {
  971. return nonstd::sv_lite::string_view {str, len};
  972. }
  973. nssv_constexpr nonstd::sv_lite::u16string_view operator"" sv(const char16_t *str, size_t len) nssv_noexcept // (2)
  974. {
  975. return nonstd::sv_lite::u16string_view {str, len};
  976. }
  977. nssv_constexpr nonstd::sv_lite::u32string_view operator"" sv(const char32_t *str, size_t len) nssv_noexcept // (3)
  978. {
  979. return nonstd::sv_lite::u32string_view {str, len};
  980. }
  981. nssv_constexpr nonstd::sv_lite::wstring_view operator"" sv(const wchar_t *str, size_t len) nssv_noexcept // (4)
  982. {
  983. return nonstd::sv_lite::wstring_view {str, len};
  984. }
  985. #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
  986. #if nssv_CONFIG_USR_SV_OPERATOR
  987. nssv_constexpr nonstd::sv_lite::string_view operator"" _sv(const char *str, size_t len) nssv_noexcept // (1)
  988. {
  989. return nonstd::sv_lite::string_view {str, len};
  990. }
  991. nssv_constexpr nonstd::sv_lite::u16string_view operator"" _sv(const char16_t *str, size_t len) nssv_noexcept // (2)
  992. {
  993. return nonstd::sv_lite::u16string_view {str, len};
  994. }
  995. nssv_constexpr nonstd::sv_lite::u32string_view operator"" _sv(const char32_t *str, size_t len) nssv_noexcept // (3)
  996. {
  997. return nonstd::sv_lite::u32string_view {str, len};
  998. }
  999. nssv_constexpr nonstd::sv_lite::wstring_view operator"" _sv(const wchar_t *str, size_t len) nssv_noexcept // (4)
  1000. {
  1001. return nonstd::sv_lite::wstring_view {str, len};
  1002. }
  1003. #endif // nssv_CONFIG_USR_SV_OPERATOR
  1004. }
  1005. }
  1006. } // namespace nonstd
  1007. #endif
  1008. //
  1009. // Extensions for std::string:
  1010. //
  1011. #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  1012. namespace nonstd {
  1013. namespace sv_lite {
  1014. // Exclude MSVC 14 (19.00): it yields ambiguous to_string():
  1015. #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
  1016. template <class CharT, class Traits, class Allocator = std::allocator<CharT>>
  1017. std::basic_string<CharT, Traits, Allocator> to_string(basic_string_view<CharT, Traits> v,
  1018. Allocator const &a = Allocator()) {
  1019. return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
  1020. }
  1021. #else
  1022. template <class CharT, class Traits> std::basic_string<CharT, Traits> to_string(basic_string_view<CharT, Traits> v) {
  1023. return std::basic_string<CharT, Traits>(v.begin(), v.end());
  1024. }
  1025. template <class CharT, class Traits, class Allocator>
  1026. std::basic_string<CharT, Traits, Allocator> to_string(basic_string_view<CharT, Traits> v, Allocator const &a) {
  1027. return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
  1028. }
  1029. #endif // nssv_CPP11_OR_GREATER
  1030. template <class CharT, class Traits, class Allocator>
  1031. basic_string_view<CharT, Traits> to_string_view(std::basic_string<CharT, Traits, Allocator> const &s) {
  1032. return basic_string_view<CharT, Traits>(s.data(), s.size());
  1033. }
  1034. } // namespace sv_lite
  1035. } // namespace nonstd
  1036. #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  1037. //
  1038. // make types and algorithms available in namespace nonstd:
  1039. //
  1040. namespace nonstd {
  1041. using sv_lite::basic_string_view;
  1042. using sv_lite::string_view;
  1043. using sv_lite::wstring_view;
  1044. #if nssv_HAVE_WCHAR16_T
  1045. using sv_lite::u16string_view;
  1046. #endif
  1047. #if nssv_HAVE_WCHAR32_T
  1048. using sv_lite::u32string_view;
  1049. #endif
  1050. // literal "sv"
  1051. using sv_lite::operator==;
  1052. using sv_lite::operator!=;
  1053. using sv_lite::operator<;
  1054. using sv_lite::operator<=;
  1055. using sv_lite::operator>;
  1056. using sv_lite::operator>=;
  1057. using sv_lite::operator<<;
  1058. #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  1059. using sv_lite::to_string;
  1060. using sv_lite::to_string_view;
  1061. #endif
  1062. } // namespace nonstd
  1063. // 24.4.5 Hash support (C++11):
  1064. // Note: The hash value of a string view object is equal to the hash value of
  1065. // the corresponding string object.
  1066. #if nssv_HAVE_STD_HASH
  1067. #include <functional>
  1068. namespace std {
  1069. template <> struct hash<nonstd::string_view> {
  1070. public:
  1071. std::size_t operator()(nonstd::string_view v) const nssv_noexcept {
  1072. return std::hash<std::string>()(std::string(v.data(), v.size()));
  1073. }
  1074. };
  1075. template <> struct hash<nonstd::wstring_view> {
  1076. public:
  1077. std::size_t operator()(nonstd::wstring_view v) const nssv_noexcept {
  1078. return std::hash<std::wstring>()(std::wstring(v.data(), v.size()));
  1079. }
  1080. };
  1081. template <> struct hash<nonstd::u16string_view> {
  1082. public:
  1083. std::size_t operator()(nonstd::u16string_view v) const nssv_noexcept {
  1084. return std::hash<std::u16string>()(std::u16string(v.data(), v.size()));
  1085. }
  1086. };
  1087. template <> struct hash<nonstd::u32string_view> {
  1088. public:
  1089. std::size_t operator()(nonstd::u32string_view v) const nssv_noexcept {
  1090. return std::hash<std::u32string>()(std::u32string(v.data(), v.size()));
  1091. }
  1092. };
  1093. } // namespace std
  1094. #endif // nssv_HAVE_STD_HASH
  1095. nssv_RESTORE_WARNINGS()
  1096. #endif // nssv_HAVE_STD_STRING_VIEW
  1097. #endif // NONSTD_SV_LITE_H_INCLUDED
  1098. namespace inja {
  1099. /*!
  1100. * \brief Class for lexer configuration.
  1101. */
  1102. struct LexerConfig {
  1103. std::string statement_open {"{%"};
  1104. std::string statement_open_no_lstrip {"{%+"};
  1105. std::string statement_open_force_lstrip {"{%-"};
  1106. std::string statement_close {"%}"};
  1107. std::string statement_close_force_rstrip {"-%}"};
  1108. std::string line_statement {"##"};
  1109. std::string expression_open {"{{"};
  1110. std::string expression_open_force_lstrip {"{{-"};
  1111. std::string expression_close {"}}"};
  1112. std::string expression_close_force_rstrip {"-}}"};
  1113. std::string comment_open {"{#"};
  1114. std::string comment_close {"#}"};
  1115. std::string open_chars {"#{"};
  1116. bool trim_blocks {false};
  1117. bool lstrip_blocks {false};
  1118. void update_open_chars() {
  1119. open_chars = "";
  1120. if (open_chars.find(line_statement[0]) == std::string::npos) {
  1121. open_chars += line_statement[0];
  1122. }
  1123. if (open_chars.find(statement_open[0]) == std::string::npos) {
  1124. open_chars += statement_open[0];
  1125. }
  1126. if (open_chars.find(statement_open_no_lstrip[0]) == std::string::npos) {
  1127. open_chars += statement_open_no_lstrip[0];
  1128. }
  1129. if (open_chars.find(statement_open_force_lstrip[0]) == std::string::npos) {
  1130. open_chars += statement_open_force_lstrip[0];
  1131. }
  1132. if (open_chars.find(expression_open[0]) == std::string::npos) {
  1133. open_chars += expression_open[0];
  1134. }
  1135. if (open_chars.find(expression_open_force_lstrip[0]) == std::string::npos) {
  1136. open_chars += expression_open_force_lstrip[0];
  1137. }
  1138. if (open_chars.find(comment_open[0]) == std::string::npos) {
  1139. open_chars += comment_open[0];
  1140. }
  1141. }
  1142. };
  1143. /*!
  1144. * \brief Class for parser configuration.
  1145. */
  1146. struct ParserConfig {
  1147. bool search_included_templates_in_files {true};
  1148. /// Extra options for limiting included files' scope
  1149. bool include_scope_limit = false;
  1150. std::string include_scope = "templates";
  1151. };
  1152. /*!
  1153. * \brief Class for render configuration.
  1154. */
  1155. struct RenderConfig {
  1156. bool throw_at_missing_includes {true};
  1157. };
  1158. } // namespace inja
  1159. #endif // INCLUDE_INJA_CONFIG_HPP_
  1160. // #include "function_storage.hpp"
  1161. // Copyright (c) 2020 Pantor. All rights reserved.
  1162. #ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
  1163. #define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
  1164. #include <vector>
  1165. // #include "string_view.hpp"
  1166. namespace inja {
  1167. using json = nlohmann::json;
  1168. using Arguments = std::vector<const json *>;
  1169. using CallbackFunction = std::function<json(Arguments &args)>;
  1170. using VoidCallbackFunction = std::function<void(Arguments &args)>;
  1171. /*!
  1172. * \brief Class for builtin functions and user-defined callbacks.
  1173. */
  1174. class FunctionStorage {
  1175. public:
  1176. enum class Operation {
  1177. Not,
  1178. And,
  1179. Or,
  1180. In,
  1181. Equal,
  1182. NotEqual,
  1183. Greater,
  1184. GreaterEqual,
  1185. Less,
  1186. LessEqual,
  1187. Add,
  1188. Subtract,
  1189. Multiplication,
  1190. Division,
  1191. Power,
  1192. Modulo,
  1193. AtId,
  1194. At,
  1195. Default,
  1196. DivisibleBy,
  1197. Even,
  1198. Exists,
  1199. ExistsInObject,
  1200. First,
  1201. Float,
  1202. Int,
  1203. IsArray,
  1204. IsBoolean,
  1205. IsFloat,
  1206. IsInteger,
  1207. IsNumber,
  1208. IsObject,
  1209. IsString,
  1210. Last,
  1211. Length,
  1212. Lower,
  1213. Max,
  1214. Min,
  1215. Odd,
  1216. Range,
  1217. Round,
  1218. Sort,
  1219. Upper,
  1220. Callback,
  1221. ParenLeft,
  1222. ParenRight,
  1223. None,
  1224. };
  1225. struct FunctionData {
  1226. explicit FunctionData(const Operation &op, const CallbackFunction &cb = CallbackFunction{}) : operation(op), callback(cb) {}
  1227. const Operation operation;
  1228. const CallbackFunction callback;
  1229. };
  1230. private:
  1231. const int VARIADIC {-1};
  1232. std::map<std::pair<std::string, int>, FunctionData> function_storage = {
  1233. {std::make_pair("at", 2), FunctionData { Operation::At }},
  1234. {std::make_pair("default", 2), FunctionData { Operation::Default }},
  1235. {std::make_pair("divisibleBy", 2), FunctionData { Operation::DivisibleBy }},
  1236. {std::make_pair("even", 1), FunctionData { Operation::Even }},
  1237. {std::make_pair("exists", 1), FunctionData { Operation::Exists }},
  1238. {std::make_pair("existsIn", 2), FunctionData { Operation::ExistsInObject }},
  1239. {std::make_pair("first", 1), FunctionData { Operation::First }},
  1240. {std::make_pair("float", 1), FunctionData { Operation::Float }},
  1241. {std::make_pair("int", 1), FunctionData { Operation::Int }},
  1242. {std::make_pair("isArray", 1), FunctionData { Operation::IsArray }},
  1243. {std::make_pair("isBoolean", 1), FunctionData { Operation::IsBoolean }},
  1244. {std::make_pair("isFloat", 1), FunctionData { Operation::IsFloat }},
  1245. {std::make_pair("isInteger", 1), FunctionData { Operation::IsInteger }},
  1246. {std::make_pair("isNumber", 1), FunctionData { Operation::IsNumber }},
  1247. {std::make_pair("isObject", 1), FunctionData { Operation::IsObject }},
  1248. {std::make_pair("isString", 1), FunctionData { Operation::IsString }},
  1249. {std::make_pair("last", 1), FunctionData { Operation::Last }},
  1250. {std::make_pair("length", 1), FunctionData { Operation::Length }},
  1251. {std::make_pair("lower", 1), FunctionData { Operation::Lower }},
  1252. {std::make_pair("max", 1), FunctionData { Operation::Max }},
  1253. {std::make_pair("min", 1), FunctionData { Operation::Min }},
  1254. {std::make_pair("odd", 1), FunctionData { Operation::Odd }},
  1255. {std::make_pair("range", 1), FunctionData { Operation::Range }},
  1256. {std::make_pair("round", 2), FunctionData { Operation::Round }},
  1257. {std::make_pair("sort", 1), FunctionData { Operation::Sort }},
  1258. {std::make_pair("upper", 1), FunctionData { Operation::Upper }},
  1259. };
  1260. public:
  1261. void add_builtin(nonstd::string_view name, int num_args, Operation op) {
  1262. function_storage.emplace(std::make_pair(static_cast<std::string>(name), num_args), FunctionData { op });
  1263. }
  1264. void add_callback(nonstd::string_view name, int num_args, const CallbackFunction &callback) {
  1265. function_storage.emplace(std::make_pair(static_cast<std::string>(name), num_args), FunctionData { Operation::Callback, callback });
  1266. }
  1267. FunctionData find_function(nonstd::string_view name, int num_args) const {
  1268. auto it = function_storage.find(std::make_pair(static_cast<std::string>(name), num_args));
  1269. if (it != function_storage.end()) {
  1270. return it->second;
  1271. // Find variadic function
  1272. } else if (num_args > 0) {
  1273. it = function_storage.find(std::make_pair(static_cast<std::string>(name), VARIADIC));
  1274. if (it != function_storage.end()) {
  1275. return it->second;
  1276. }
  1277. }
  1278. return FunctionData { Operation::None };
  1279. }
  1280. };
  1281. } // namespace inja
  1282. #endif // INCLUDE_INJA_FUNCTION_STORAGE_HPP_
  1283. // #include "parser.hpp"
  1284. // Copyright (c) 2020 Pantor. All rights reserved.
  1285. #ifndef INCLUDE_INJA_PARSER_HPP_
  1286. #define INCLUDE_INJA_PARSER_HPP_
  1287. #include <limits>
  1288. #include <stack>
  1289. #include <string>
  1290. #include <utility>
  1291. #include <queue>
  1292. #include <vector>
  1293. // #include "config.hpp"
  1294. // #include "exceptions.hpp"
  1295. // Copyright (c) 2020 Pantor. All rights reserved.
  1296. #ifndef INCLUDE_INJA_EXCEPTIONS_HPP_
  1297. #define INCLUDE_INJA_EXCEPTIONS_HPP_
  1298. #include <stdexcept>
  1299. #include <string>
  1300. namespace inja {
  1301. struct SourceLocation {
  1302. size_t line;
  1303. size_t column;
  1304. };
  1305. struct InjaError : public std::runtime_error {
  1306. const std::string type;
  1307. const std::string message;
  1308. const SourceLocation location;
  1309. explicit InjaError(const std::string &type, const std::string &message)
  1310. : std::runtime_error("[inja.exception." + type + "] " + message), type(type), message(message), location({0, 0}) {}
  1311. explicit InjaError(const std::string &type, const std::string &message, SourceLocation location)
  1312. : std::runtime_error("[inja.exception." + type + "] (at " + std::to_string(location.line) + ":" +
  1313. std::to_string(location.column) + ") " + message),
  1314. type(type), message(message), location(location) {}
  1315. };
  1316. struct ParserError : public InjaError {
  1317. explicit ParserError(const std::string &message, SourceLocation location) : InjaError("parser_error", message, location) {}
  1318. };
  1319. struct RenderError : public InjaError {
  1320. explicit RenderError(const std::string &message, SourceLocation location) : InjaError("render_error", message, location) {}
  1321. };
  1322. struct FileError : public InjaError {
  1323. explicit FileError(const std::string &message) : InjaError("file_error", message) {}
  1324. explicit FileError(const std::string &message, SourceLocation location) : InjaError("file_error", message, location) {}
  1325. };
  1326. struct JsonError : public InjaError {
  1327. explicit JsonError(const std::string &message, SourceLocation location) : InjaError("json_error", message, location) {}
  1328. };
  1329. } // namespace inja
  1330. #endif // INCLUDE_INJA_EXCEPTIONS_HPP_
  1331. // #include "function_storage.hpp"
  1332. // #include "lexer.hpp"
  1333. // Copyright (c) 2020 Pantor. All rights reserved.
  1334. #ifndef INCLUDE_INJA_LEXER_HPP_
  1335. #define INCLUDE_INJA_LEXER_HPP_
  1336. #include <cctype>
  1337. #include <locale>
  1338. // #include "config.hpp"
  1339. // #include "token.hpp"
  1340. // Copyright (c) 2020 Pantor. All rights reserved.
  1341. #ifndef INCLUDE_INJA_TOKEN_HPP_
  1342. #define INCLUDE_INJA_TOKEN_HPP_
  1343. #include <string>
  1344. // #include "string_view.hpp"
  1345. namespace inja {
  1346. /*!
  1347. * \brief Helper-class for the inja Lexer.
  1348. */
  1349. struct Token {
  1350. enum class Kind {
  1351. Text,
  1352. ExpressionOpen, // {{
  1353. ExpressionClose, // }}
  1354. LineStatementOpen, // ##
  1355. LineStatementClose, // \n
  1356. StatementOpen, // {%
  1357. StatementClose, // %}
  1358. CommentOpen, // {#
  1359. CommentClose, // #}
  1360. Id, // this, this.foo
  1361. Number, // 1, 2, -1, 5.2, -5.3
  1362. String, // "this"
  1363. Plus, // +
  1364. Minus, // -
  1365. Times, // *
  1366. Slash, // /
  1367. Percent, // %
  1368. Power, // ^
  1369. Comma, // ,
  1370. Dot, // .
  1371. Colon, // :
  1372. LeftParen, // (
  1373. RightParen, // )
  1374. LeftBracket, // [
  1375. RightBracket, // ]
  1376. LeftBrace, // {
  1377. RightBrace, // }
  1378. Equal, // ==
  1379. NotEqual, // !=
  1380. GreaterThan, // >
  1381. GreaterEqual, // >=
  1382. LessThan, // <
  1383. LessEqual, // <=
  1384. Unknown,
  1385. Eof,
  1386. };
  1387. Kind kind {Kind::Unknown};
  1388. nonstd::string_view text;
  1389. explicit constexpr Token() = default;
  1390. explicit constexpr Token(Kind kind, nonstd::string_view text) : kind(kind), text(text) {}
  1391. std::string describe() const {
  1392. switch (kind) {
  1393. case Kind::Text:
  1394. return "<text>";
  1395. case Kind::LineStatementClose:
  1396. return "<eol>";
  1397. case Kind::Eof:
  1398. return "<eof>";
  1399. default:
  1400. return static_cast<std::string>(text);
  1401. }
  1402. }
  1403. };
  1404. } // namespace inja
  1405. #endif // INCLUDE_INJA_TOKEN_HPP_
  1406. // #include "utils.hpp"
  1407. // Copyright (c) 2020 Pantor. All rights reserved.
  1408. #ifndef INCLUDE_INJA_UTILS_HPP_
  1409. #define INCLUDE_INJA_UTILS_HPP_
  1410. #include <algorithm>
  1411. #include <fstream>
  1412. #include <string>
  1413. #include <utility>
  1414. // #include "exceptions.hpp"
  1415. // #include "string_view.hpp"
  1416. namespace inja {
  1417. inline void open_file_or_throw(const std::string &path, std::ifstream &file) {
  1418. file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
  1419. try {
  1420. file.open(path);
  1421. } catch (const std::ios_base::failure & /*e*/) {
  1422. throw FileError("failed accessing file at '" + path + "'");
  1423. }
  1424. }
  1425. namespace string_view {
  1426. inline nonstd::string_view slice(nonstd::string_view view, size_t start, size_t end) {
  1427. start = std::min(start, view.size());
  1428. end = std::min(std::max(start, end), view.size());
  1429. return view.substr(start, end - start);
  1430. }
  1431. inline std::pair<nonstd::string_view, nonstd::string_view> split(nonstd::string_view view, char Separator) {
  1432. size_t idx = view.find(Separator);
  1433. if (idx == nonstd::string_view::npos) {
  1434. return std::make_pair(view, nonstd::string_view());
  1435. }
  1436. return std::make_pair(slice(view, 0, idx), slice(view, idx + 1, nonstd::string_view::npos));
  1437. }
  1438. inline bool starts_with(nonstd::string_view view, nonstd::string_view prefix) {
  1439. return (view.size() >= prefix.size() && view.compare(0, prefix.size(), prefix) == 0);
  1440. }
  1441. } // namespace string_view
  1442. inline SourceLocation get_source_location(nonstd::string_view content, size_t pos) {
  1443. // Get line and offset position (starts at 1:1)
  1444. auto sliced = string_view::slice(content, 0, pos);
  1445. std::size_t last_newline = sliced.rfind("\n");
  1446. if (last_newline == nonstd::string_view::npos) {
  1447. return {1, sliced.length() + 1};
  1448. }
  1449. // Count newlines
  1450. size_t count_lines = 0;
  1451. size_t search_start = 0;
  1452. while (search_start <= sliced.size()) {
  1453. search_start = sliced.find("\n", search_start) + 1;
  1454. if (search_start == 0) {
  1455. break;
  1456. }
  1457. count_lines += 1;
  1458. }
  1459. return {count_lines + 1, sliced.length() - last_newline};
  1460. }
  1461. } // namespace inja
  1462. #endif // INCLUDE_INJA_UTILS_HPP_
  1463. namespace inja {
  1464. /*!
  1465. * \brief Class for lexing an inja Template.
  1466. */
  1467. class Lexer {
  1468. enum class State {
  1469. Text,
  1470. ExpressionStart,
  1471. ExpressionStartForceLstrip,
  1472. ExpressionBody,
  1473. LineStart,
  1474. LineBody,
  1475. StatementStart,
  1476. StatementStartNoLstrip,
  1477. StatementStartForceLstrip,
  1478. StatementBody,
  1479. CommentStart,
  1480. CommentBody,
  1481. };
  1482. enum class MinusState {
  1483. Operator,
  1484. Number,
  1485. };
  1486. const LexerConfig &config;
  1487. State state;
  1488. MinusState minus_state;
  1489. nonstd::string_view m_in;
  1490. size_t tok_start;
  1491. size_t pos;
  1492. Token scan_body(nonstd::string_view close, Token::Kind closeKind, nonstd::string_view close_trim = nonstd::string_view(), bool trim = false) {
  1493. again:
  1494. // skip whitespace (except for \n as it might be a close)
  1495. if (tok_start >= m_in.size()) {
  1496. return make_token(Token::Kind::Eof);
  1497. }
  1498. char ch = m_in[tok_start];
  1499. if (ch == ' ' || ch == '\t' || ch == '\r') {
  1500. tok_start += 1;
  1501. goto again;
  1502. }
  1503. // check for close
  1504. if (!close_trim.empty() && inja::string_view::starts_with(m_in.substr(tok_start), close_trim)) {
  1505. state = State::Text;
  1506. pos = tok_start + close_trim.size();
  1507. Token tok = make_token(closeKind);
  1508. skip_whitespaces_and_newlines();
  1509. return tok;
  1510. }
  1511. if (inja::string_view::starts_with(m_in.substr(tok_start), close)) {
  1512. state = State::Text;
  1513. pos = tok_start + close.size();
  1514. Token tok = make_token(closeKind);
  1515. if (trim) {
  1516. skip_whitespaces_and_first_newline();
  1517. }
  1518. return tok;
  1519. }
  1520. // skip \n
  1521. if (ch == '\n') {
  1522. tok_start += 1;
  1523. goto again;
  1524. }
  1525. pos = tok_start + 1;
  1526. if (std::isalpha(ch)) {
  1527. minus_state = MinusState::Operator;
  1528. return scan_id();
  1529. }
  1530. MinusState current_minus_state = minus_state;
  1531. if (minus_state == MinusState::Operator) {
  1532. minus_state = MinusState::Number;
  1533. }
  1534. switch (ch) {
  1535. case '+':
  1536. return make_token(Token::Kind::Plus);
  1537. case '-':
  1538. if (current_minus_state == MinusState::Operator) {
  1539. return make_token(Token::Kind::Minus);
  1540. }
  1541. return scan_number();
  1542. case '*':
  1543. return make_token(Token::Kind::Times);
  1544. case '/':
  1545. return make_token(Token::Kind::Slash);
  1546. case '^':
  1547. return make_token(Token::Kind::Power);
  1548. case '%':
  1549. return make_token(Token::Kind::Percent);
  1550. case '.':
  1551. return make_token(Token::Kind::Dot);
  1552. case ',':
  1553. return make_token(Token::Kind::Comma);
  1554. case ':':
  1555. return make_token(Token::Kind::Colon);
  1556. case '(':
  1557. return make_token(Token::Kind::LeftParen);
  1558. case ')':
  1559. minus_state = MinusState::Operator;
  1560. return make_token(Token::Kind::RightParen);
  1561. case '[':
  1562. return make_token(Token::Kind::LeftBracket);
  1563. case ']':
  1564. minus_state = MinusState::Operator;
  1565. return make_token(Token::Kind::RightBracket);
  1566. case '{':
  1567. return make_token(Token::Kind::LeftBrace);
  1568. case '}':
  1569. minus_state = MinusState::Operator;
  1570. return make_token(Token::Kind::RightBrace);
  1571. case '>':
  1572. if (pos < m_in.size() && m_in[pos] == '=') {
  1573. pos += 1;
  1574. return make_token(Token::Kind::GreaterEqual);
  1575. }
  1576. return make_token(Token::Kind::GreaterThan);
  1577. case '<':
  1578. if (pos < m_in.size() && m_in[pos] == '=') {
  1579. pos += 1;
  1580. return make_token(Token::Kind::LessEqual);
  1581. }
  1582. return make_token(Token::Kind::LessThan);
  1583. case '=':
  1584. if (pos < m_in.size() && m_in[pos] == '=') {
  1585. pos += 1;
  1586. return make_token(Token::Kind::Equal);
  1587. }
  1588. return make_token(Token::Kind::Unknown);
  1589. case '!':
  1590. if (pos < m_in.size() && m_in[pos] == '=') {
  1591. pos += 1;
  1592. return make_token(Token::Kind::NotEqual);
  1593. }
  1594. return make_token(Token::Kind::Unknown);
  1595. case '\"':
  1596. return scan_string();
  1597. case '0':
  1598. case '1':
  1599. case '2':
  1600. case '3':
  1601. case '4':
  1602. case '5':
  1603. case '6':
  1604. case '7':
  1605. case '8':
  1606. case '9':
  1607. minus_state = MinusState::Operator;
  1608. return scan_number();
  1609. case '_':
  1610. minus_state = MinusState::Operator;
  1611. return scan_id();
  1612. default:
  1613. return make_token(Token::Kind::Unknown);
  1614. }
  1615. }
  1616. Token scan_id() {
  1617. for (;;) {
  1618. if (pos >= m_in.size()) {
  1619. break;
  1620. }
  1621. char ch = m_in[pos];
  1622. if (!std::isalnum(ch) && ch != '.' && ch != '/' && ch != '_' && ch != '-') {
  1623. break;
  1624. }
  1625. pos += 1;
  1626. }
  1627. return make_token(Token::Kind::Id);
  1628. }
  1629. Token scan_number() {
  1630. for (;;) {
  1631. if (pos >= m_in.size()) {
  1632. break;
  1633. }
  1634. char ch = m_in[pos];
  1635. // be very permissive in lexer (we'll catch errors when conversion happens)
  1636. if (!std::isdigit(ch) && ch != '.' && ch != 'e' && ch != 'E' && ch != '+' && ch != '-') {
  1637. break;
  1638. }
  1639. pos += 1;
  1640. }
  1641. return make_token(Token::Kind::Number);
  1642. }
  1643. Token scan_string() {
  1644. bool escape {false};
  1645. for (;;) {
  1646. if (pos >= m_in.size()) {
  1647. break;
  1648. }
  1649. char ch = m_in[pos++];
  1650. if (ch == '\\') {
  1651. escape = true;
  1652. } else if (!escape && ch == m_in[tok_start]) {
  1653. break;
  1654. } else {
  1655. escape = false;
  1656. }
  1657. }
  1658. return make_token(Token::Kind::String);
  1659. }
  1660. Token make_token(Token::Kind kind) const { return Token(kind, string_view::slice(m_in, tok_start, pos)); }
  1661. void skip_whitespaces_and_newlines() {
  1662. if (pos < m_in.size()) {
  1663. while (pos < m_in.size() && (m_in[pos] == ' ' || m_in[pos] == '\t' || m_in[pos] == '\n' || m_in[pos] == '\r')) {
  1664. pos += 1;
  1665. }
  1666. }
  1667. }
  1668. void skip_whitespaces_and_first_newline() {
  1669. if (pos < m_in.size()) {
  1670. while (pos < m_in.size() && (m_in[pos] == ' ' || m_in[pos] == '\t')) {
  1671. pos += 1;
  1672. }
  1673. }
  1674. if (pos < m_in.size()) {
  1675. char ch = m_in[pos];
  1676. if (ch == '\n') {
  1677. pos += 1;
  1678. } else if (ch == '\r') {
  1679. pos += 1;
  1680. if (pos < m_in.size() && m_in[pos] == '\n') {
  1681. pos += 1;
  1682. }
  1683. }
  1684. }
  1685. }
  1686. static nonstd::string_view clear_final_line_if_whitespace(nonstd::string_view text) {
  1687. nonstd::string_view result = text;
  1688. while (!result.empty()) {
  1689. char ch = result.back();
  1690. if (ch == ' ' || ch == '\t') {
  1691. result.remove_suffix(1);
  1692. } else if (ch == '\n' || ch == '\r') {
  1693. break;
  1694. } else {
  1695. return text;
  1696. }
  1697. }
  1698. return result;
  1699. }
  1700. public:
  1701. explicit Lexer(const LexerConfig &config) : config(config), state(State::Text), minus_state(MinusState::Number) {}
  1702. SourceLocation current_position() const {
  1703. return get_source_location(m_in, tok_start);
  1704. }
  1705. void start(nonstd::string_view input) {
  1706. m_in = input;
  1707. tok_start = 0;
  1708. pos = 0;
  1709. state = State::Text;
  1710. minus_state = MinusState::Number;
  1711. // Consume byte order mark (BOM) for UTF-8
  1712. if (inja::string_view::starts_with(m_in, "\xEF\xBB\xBF")) {
  1713. m_in = m_in.substr(3);
  1714. }
  1715. }
  1716. Token scan() {
  1717. tok_start = pos;
  1718. again:
  1719. if (tok_start >= m_in.size()) {
  1720. return make_token(Token::Kind::Eof);
  1721. }
  1722. switch (state) {
  1723. default:
  1724. case State::Text: {
  1725. // fast-scan to first open character
  1726. size_t open_start = m_in.substr(pos).find_first_of(config.open_chars);
  1727. if (open_start == nonstd::string_view::npos) {
  1728. // didn't find open, return remaining text as text token
  1729. pos = m_in.size();
  1730. return make_token(Token::Kind::Text);
  1731. }
  1732. pos += open_start;
  1733. // try to match one of the opening sequences, and get the close
  1734. nonstd::string_view open_str = m_in.substr(pos);
  1735. bool must_lstrip = false;
  1736. if (inja::string_view::starts_with(open_str, config.expression_open)) {
  1737. if (inja::string_view::starts_with(open_str, config.expression_open_force_lstrip)) {
  1738. state = State::ExpressionStartForceLstrip;
  1739. must_lstrip = true;
  1740. } else {
  1741. state = State::ExpressionStart;
  1742. }
  1743. } else if (inja::string_view::starts_with(open_str, config.statement_open)) {
  1744. if (inja::string_view::starts_with(open_str, config.statement_open_no_lstrip)) {
  1745. state = State::StatementStartNoLstrip;
  1746. } else if (inja::string_view::starts_with(open_str, config.statement_open_force_lstrip )) {
  1747. state = State::StatementStartForceLstrip;
  1748. must_lstrip = true;
  1749. } else {
  1750. state = State::StatementStart;
  1751. must_lstrip = config.lstrip_blocks;
  1752. }
  1753. } else if (inja::string_view::starts_with(open_str, config.comment_open)) {
  1754. state = State::CommentStart;
  1755. must_lstrip = config.lstrip_blocks;
  1756. } else if ((pos == 0 || m_in[pos - 1] == '\n') && inja::string_view::starts_with(open_str, config.line_statement)) {
  1757. state = State::LineStart;
  1758. } else {
  1759. pos += 1; // wasn't actually an opening sequence
  1760. goto again;
  1761. }
  1762. nonstd::string_view text = string_view::slice(m_in, tok_start, pos);
  1763. if (must_lstrip) {
  1764. text = clear_final_line_if_whitespace(text);
  1765. }
  1766. if (text.empty()) {
  1767. goto again; // don't generate empty token
  1768. }
  1769. return Token(Token::Kind::Text, text);
  1770. }
  1771. case State::ExpressionStart: {
  1772. state = State::ExpressionBody;
  1773. pos += config.expression_open.size();
  1774. return make_token(Token::Kind::ExpressionOpen);
  1775. }
  1776. case State::ExpressionStartForceLstrip: {
  1777. state = State::ExpressionBody;
  1778. pos += config.expression_open_force_lstrip.size();
  1779. return make_token(Token::Kind::ExpressionOpen);
  1780. }
  1781. case State::LineStart: {
  1782. state = State::LineBody;
  1783. pos += config.line_statement.size();
  1784. return make_token(Token::Kind::LineStatementOpen);
  1785. }
  1786. case State::StatementStart: {
  1787. state = State::StatementBody;
  1788. pos += config.statement_open.size();
  1789. return make_token(Token::Kind::StatementOpen);
  1790. }
  1791. case State::StatementStartNoLstrip: {
  1792. state = State::StatementBody;
  1793. pos += config.statement_open_no_lstrip.size();
  1794. return make_token(Token::Kind::StatementOpen);
  1795. }
  1796. case State::StatementStartForceLstrip: {
  1797. state = State::StatementBody;
  1798. pos += config.statement_open_force_lstrip.size();
  1799. return make_token(Token::Kind::StatementOpen);
  1800. }
  1801. case State::CommentStart: {
  1802. state = State::CommentBody;
  1803. pos += config.comment_open.size();
  1804. return make_token(Token::Kind::CommentOpen);
  1805. }
  1806. case State::ExpressionBody:
  1807. return scan_body(config.expression_close, Token::Kind::ExpressionClose, config.expression_close_force_rstrip);
  1808. case State::LineBody:
  1809. return scan_body("\n", Token::Kind::LineStatementClose);
  1810. case State::StatementBody:
  1811. return scan_body(config.statement_close, Token::Kind::StatementClose, config.statement_close_force_rstrip, config.trim_blocks);
  1812. case State::CommentBody: {
  1813. // fast-scan to comment close
  1814. size_t end = m_in.substr(pos).find(config.comment_close);
  1815. if (end == nonstd::string_view::npos) {
  1816. pos = m_in.size();
  1817. return make_token(Token::Kind::Eof);
  1818. }
  1819. // return the entire comment in the close token
  1820. state = State::Text;
  1821. pos += end + config.comment_close.size();
  1822. Token tok = make_token(Token::Kind::CommentClose);
  1823. if (config.trim_blocks) {
  1824. skip_whitespaces_and_first_newline();
  1825. }
  1826. return tok;
  1827. }
  1828. }
  1829. }
  1830. const LexerConfig &get_config() const {
  1831. return config;
  1832. }
  1833. };
  1834. } // namespace inja
  1835. #endif // INCLUDE_INJA_LEXER_HPP_
  1836. // #include "node.hpp"
  1837. // Copyright (c) 2020 Pantor. All rights reserved.
  1838. #ifndef INCLUDE_INJA_NODE_HPP_
  1839. #define INCLUDE_INJA_NODE_HPP_
  1840. #include <string>
  1841. #include <utility>
  1842. #include <nlohmann/json.hpp>
  1843. // #include "function_storage.hpp"
  1844. // #include "string_view.hpp"
  1845. namespace inja {
  1846. class NodeVisitor;
  1847. class BlockNode;
  1848. class TextNode;
  1849. class ExpressionNode;
  1850. class LiteralNode;
  1851. class JsonNode;
  1852. class FunctionNode;
  1853. class ExpressionListNode;
  1854. class StatementNode;
  1855. class ForStatementNode;
  1856. class ForArrayStatementNode;
  1857. class ForObjectStatementNode;
  1858. class IfStatementNode;
  1859. class IncludeStatementNode;
  1860. class SetStatementNode;
  1861. class NodeVisitor {
  1862. public:
  1863. virtual void visit(const BlockNode& node) = 0;
  1864. virtual void visit(const TextNode& node) = 0;
  1865. virtual void visit(const ExpressionNode& node) = 0;
  1866. virtual void visit(const LiteralNode& node) = 0;
  1867. virtual void visit(const JsonNode& node) = 0;
  1868. virtual void visit(const FunctionNode& node) = 0;
  1869. virtual void visit(const ExpressionListNode& node) = 0;
  1870. virtual void visit(const StatementNode& node) = 0;
  1871. virtual void visit(const ForStatementNode& node) = 0;
  1872. virtual void visit(const ForArrayStatementNode& node) = 0;
  1873. virtual void visit(const ForObjectStatementNode& node) = 0;
  1874. virtual void visit(const IfStatementNode& node) = 0;
  1875. virtual void visit(const IncludeStatementNode& node) = 0;
  1876. virtual void visit(const SetStatementNode& node) = 0;
  1877. };
  1878. /*!
  1879. * \brief Base node class for the abstract syntax tree (AST).
  1880. */
  1881. class AstNode {
  1882. public:
  1883. virtual void accept(NodeVisitor& v) const = 0;
  1884. size_t pos;
  1885. AstNode(size_t pos) : pos(pos) { }
  1886. virtual ~AstNode() { };
  1887. };
  1888. class BlockNode : public AstNode {
  1889. public:
  1890. std::vector<std::shared_ptr<AstNode>> nodes;
  1891. explicit BlockNode() : AstNode(0) {}
  1892. void accept(NodeVisitor& v) const {
  1893. v.visit(*this);
  1894. }
  1895. };
  1896. class TextNode : public AstNode {
  1897. public:
  1898. const size_t length;
  1899. explicit TextNode(size_t pos, size_t length): AstNode(pos), length(length) { }
  1900. void accept(NodeVisitor& v) const {
  1901. v.visit(*this);
  1902. }
  1903. };
  1904. class ExpressionNode : public AstNode {
  1905. public:
  1906. explicit ExpressionNode(size_t pos) : AstNode(pos) {}
  1907. void accept(NodeVisitor& v) const {
  1908. v.visit(*this);
  1909. }
  1910. };
  1911. class LiteralNode : public ExpressionNode {
  1912. public:
  1913. const nlohmann::json value;
  1914. explicit LiteralNode(const nlohmann::json& value, size_t pos) : ExpressionNode(pos), value(value) { }
  1915. void accept(NodeVisitor& v) const {
  1916. v.visit(*this);
  1917. }
  1918. };
  1919. class JsonNode : public ExpressionNode {
  1920. public:
  1921. const std::string name;
  1922. const json::json_pointer ptr;
  1923. static std::string convert_dot_to_json_ptr(nonstd::string_view ptr_name) {
  1924. std::string result;
  1925. do {
  1926. nonstd::string_view part;
  1927. std::tie(part, ptr_name) = string_view::split(ptr_name, '.');
  1928. result.push_back('/');
  1929. result.append(part.begin(), part.end());
  1930. } while (!ptr_name.empty());
  1931. return result;
  1932. }
  1933. explicit JsonNode(nonstd::string_view ptr_name, size_t pos) : ExpressionNode(pos), name(ptr_name), ptr(json::json_pointer(convert_dot_to_json_ptr(ptr_name))) { }
  1934. void accept(NodeVisitor& v) const {
  1935. v.visit(*this);
  1936. }
  1937. };
  1938. class FunctionNode : public ExpressionNode {
  1939. using Op = FunctionStorage::Operation;
  1940. public:
  1941. enum class Associativity {
  1942. Left,
  1943. Right,
  1944. };
  1945. unsigned int precedence;
  1946. Associativity associativity;
  1947. Op operation;
  1948. std::string name;
  1949. int number_args; // Should also be negative -> -1 for unknown number
  1950. CallbackFunction callback;
  1951. explicit FunctionNode(nonstd::string_view name, size_t pos) : ExpressionNode(pos), precedence(8), associativity(Associativity::Left), operation(Op::Callback), name(name), number_args(1) { }
  1952. explicit FunctionNode(Op operation, size_t pos) : ExpressionNode(pos), operation(operation), number_args(1) {
  1953. switch (operation) {
  1954. case Op::Not: {
  1955. precedence = 4;
  1956. associativity = Associativity::Left;
  1957. } break;
  1958. case Op::And: {
  1959. precedence = 1;
  1960. associativity = Associativity::Left;
  1961. } break;
  1962. case Op::Or: {
  1963. precedence = 1;
  1964. associativity = Associativity::Left;
  1965. } break;
  1966. case Op::In: {
  1967. precedence = 2;
  1968. associativity = Associativity::Left;
  1969. } break;
  1970. case Op::Equal: {
  1971. precedence = 2;
  1972. associativity = Associativity::Left;
  1973. } break;
  1974. case Op::NotEqual: {
  1975. precedence = 2;
  1976. associativity = Associativity::Left;
  1977. } break;
  1978. case Op::Greater: {
  1979. precedence = 2;
  1980. associativity = Associativity::Left;
  1981. } break;
  1982. case Op::GreaterEqual: {
  1983. precedence = 2;
  1984. associativity = Associativity::Left;
  1985. } break;
  1986. case Op::Less: {
  1987. precedence = 2;
  1988. associativity = Associativity::Left;
  1989. } break;
  1990. case Op::LessEqual: {
  1991. precedence = 2;
  1992. associativity = Associativity::Left;
  1993. } break;
  1994. case Op::Add: {
  1995. precedence = 3;
  1996. associativity = Associativity::Left;
  1997. } break;
  1998. case Op::Subtract: {
  1999. precedence = 3;
  2000. associativity = Associativity::Left;
  2001. } break;
  2002. case Op::Multiplication: {
  2003. precedence = 4;
  2004. associativity = Associativity::Left;
  2005. } break;
  2006. case Op::Division: {
  2007. precedence = 4;
  2008. associativity = Associativity::Left;
  2009. } break;
  2010. case Op::Power: {
  2011. precedence = 5;
  2012. associativity = Associativity::Right;
  2013. } break;
  2014. case Op::Modulo: {
  2015. precedence = 4;
  2016. associativity = Associativity::Left;
  2017. } break;
  2018. case Op::AtId: {
  2019. precedence = 8;
  2020. associativity = Associativity::Left;
  2021. } break;
  2022. default: {
  2023. precedence = 1;
  2024. associativity = Associativity::Left;
  2025. }
  2026. }
  2027. }
  2028. void accept(NodeVisitor& v) const {
  2029. v.visit(*this);
  2030. }
  2031. };
  2032. class ExpressionListNode : public AstNode {
  2033. public:
  2034. std::vector<std::shared_ptr<ExpressionNode>> rpn_output;
  2035. explicit ExpressionListNode() : AstNode(0) { }
  2036. explicit ExpressionListNode(size_t pos) : AstNode(pos) { }
  2037. void accept(NodeVisitor& v) const {
  2038. v.visit(*this);
  2039. }
  2040. };
  2041. class StatementNode : public AstNode {
  2042. public:
  2043. StatementNode(size_t pos) : AstNode(pos) { }
  2044. virtual void accept(NodeVisitor& v) const = 0;
  2045. };
  2046. class ForStatementNode : public StatementNode {
  2047. public:
  2048. ExpressionListNode condition;
  2049. BlockNode body;
  2050. BlockNode *const parent;
  2051. ForStatementNode(BlockNode *const parent, size_t pos) : StatementNode(pos), parent(parent) { }
  2052. virtual void accept(NodeVisitor& v) const = 0;
  2053. };
  2054. class ForArrayStatementNode : public ForStatementNode {
  2055. public:
  2056. const std::string value;
  2057. explicit ForArrayStatementNode(const std::string& value, BlockNode *const parent, size_t pos) : ForStatementNode(parent, pos), value(value) { }
  2058. void accept(NodeVisitor& v) const {
  2059. v.visit(*this);
  2060. }
  2061. };
  2062. class ForObjectStatementNode : public ForStatementNode {
  2063. public:
  2064. const std::string key;
  2065. const std::string value;
  2066. explicit ForObjectStatementNode(const std::string& key, const std::string& value, BlockNode *const parent, size_t pos) : ForStatementNode(parent, pos), key(key), value(value) { }
  2067. void accept(NodeVisitor& v) const {
  2068. v.visit(*this);
  2069. }
  2070. };
  2071. class IfStatementNode : public StatementNode {
  2072. public:
  2073. ExpressionListNode condition;
  2074. BlockNode true_statement;
  2075. BlockNode false_statement;
  2076. BlockNode *const parent;
  2077. const bool is_nested;
  2078. bool has_false_statement {false};
  2079. explicit IfStatementNode(BlockNode *const parent, size_t pos) : StatementNode(pos), parent(parent), is_nested(false) { }
  2080. explicit IfStatementNode(bool is_nested, BlockNode *const parent, size_t pos) : StatementNode(pos), parent(parent), is_nested(is_nested) { }
  2081. void accept(NodeVisitor& v) const {
  2082. v.visit(*this);
  2083. }
  2084. };
  2085. class IncludeStatementNode : public StatementNode {
  2086. public:
  2087. const std::string file;
  2088. explicit IncludeStatementNode(const std::string& file, size_t pos) : StatementNode(pos), file(file) { }
  2089. void accept(NodeVisitor& v) const {
  2090. v.visit(*this);
  2091. };
  2092. };
  2093. class SetStatementNode : public StatementNode {
  2094. public:
  2095. const std::string key;
  2096. ExpressionListNode expression;
  2097. explicit SetStatementNode(const std::string& key, size_t pos) : StatementNode(pos), key(key) { }
  2098. void accept(NodeVisitor& v) const {
  2099. v.visit(*this);
  2100. };
  2101. };
  2102. } // namespace inja
  2103. #endif // INCLUDE_INJA_NODE_HPP_
  2104. // #include "template.hpp"
  2105. // Copyright (c) 2019 Pantor. All rights reserved.
  2106. #ifndef INCLUDE_INJA_TEMPLATE_HPP_
  2107. #define INCLUDE_INJA_TEMPLATE_HPP_
  2108. #include <map>
  2109. #include <memory>
  2110. #include <string>
  2111. #include <vector>
  2112. // #include "node.hpp"
  2113. // #include "statistics.hpp"
  2114. // Copyright (c) 2019 Pantor. All rights reserved.
  2115. #ifndef INCLUDE_INJA_STATISTICS_HPP_
  2116. #define INCLUDE_INJA_STATISTICS_HPP_
  2117. // #include "node.hpp"
  2118. namespace inja {
  2119. /*!
  2120. * \brief A class for counting statistics on a Template.
  2121. */
  2122. class StatisticsVisitor : public NodeVisitor {
  2123. void visit(const BlockNode& node) {
  2124. for (auto& n : node.nodes) {
  2125. n->accept(*this);
  2126. }
  2127. }
  2128. void visit(const TextNode&) { }
  2129. void visit(const ExpressionNode&) { }
  2130. void visit(const LiteralNode&) { }
  2131. void visit(const JsonNode&) {
  2132. variable_counter += 1;
  2133. }
  2134. void visit(const FunctionNode&) { }
  2135. void visit(const ExpressionListNode& node) {
  2136. for (auto& n : node.rpn_output) {
  2137. n->accept(*this);
  2138. }
  2139. }
  2140. void visit(const StatementNode&) { }
  2141. void visit(const ForStatementNode&) { }
  2142. void visit(const ForArrayStatementNode& node) {
  2143. node.condition.accept(*this);
  2144. node.body.accept(*this);
  2145. }
  2146. void visit(const ForObjectStatementNode& node) {
  2147. node.condition.accept(*this);
  2148. node.body.accept(*this);
  2149. }
  2150. void visit(const IfStatementNode& node) {
  2151. node.condition.accept(*this);
  2152. node.true_statement.accept(*this);
  2153. node.false_statement.accept(*this);
  2154. }
  2155. void visit(const IncludeStatementNode&) { }
  2156. void visit(const SetStatementNode&) { }
  2157. public:
  2158. unsigned int variable_counter;
  2159. explicit StatisticsVisitor() : variable_counter(0) { }
  2160. };
  2161. } // namespace inja
  2162. #endif // INCLUDE_INJA_STATISTICS_HPP_
  2163. namespace inja {
  2164. /*!
  2165. * \brief The main inja Template.
  2166. */
  2167. struct Template {
  2168. BlockNode root;
  2169. std::string content;
  2170. explicit Template() { }
  2171. explicit Template(const std::string& content): content(content) { }
  2172. /// Return number of variables (total number, not distinct ones) in the template
  2173. int count_variables() {
  2174. auto statistic_visitor = StatisticsVisitor();
  2175. root.accept(statistic_visitor);
  2176. return statistic_visitor.variable_counter;
  2177. }
  2178. };
  2179. using TemplateStorage = std::map<std::string, Template>;
  2180. } // namespace inja
  2181. #endif // INCLUDE_INJA_TEMPLATE_HPP_
  2182. // #include "token.hpp"
  2183. // #include "utils.hpp"
  2184. #include <nlohmann/json.hpp>
  2185. namespace inja {
  2186. /*!
  2187. * \brief Class for parsing an inja Template.
  2188. */
  2189. class Parser {
  2190. const ParserConfig &config;
  2191. Lexer lexer;
  2192. TemplateStorage &template_storage;
  2193. const FunctionStorage &function_storage;
  2194. Token tok, peek_tok;
  2195. bool have_peek_tok {false};
  2196. size_t current_paren_level {0};
  2197. size_t current_bracket_level {0};
  2198. size_t current_brace_level {0};
  2199. nonstd::string_view json_literal_start;
  2200. BlockNode *current_block {nullptr};
  2201. ExpressionListNode *current_expression_list {nullptr};
  2202. std::stack<std::pair<FunctionNode*, size_t>> function_stack;
  2203. std::stack<std::shared_ptr<FunctionNode>> operator_stack;
  2204. std::stack<IfStatementNode*> if_statement_stack;
  2205. std::stack<ForStatementNode*> for_statement_stack;
  2206. void throw_parser_error(const std::string &message) {
  2207. throw ParserError(message, lexer.current_position());
  2208. }
  2209. void get_next_token() {
  2210. if (have_peek_tok) {
  2211. tok = peek_tok;
  2212. have_peek_tok = false;
  2213. } else {
  2214. tok = lexer.scan();
  2215. }
  2216. }
  2217. void get_peek_token() {
  2218. if (!have_peek_tok) {
  2219. peek_tok = lexer.scan();
  2220. have_peek_tok = true;
  2221. }
  2222. }
  2223. void add_json_literal(const char* content_ptr) {
  2224. nonstd::string_view json_text(json_literal_start.data(), tok.text.data() - json_literal_start.data() + tok.text.size());
  2225. current_expression_list->rpn_output.emplace_back(std::make_shared<LiteralNode>(json::parse(json_text), json_text.data() - content_ptr));
  2226. }
  2227. bool parse_expression(Template &tmpl, Token::Kind closing) {
  2228. while (tok.kind != closing && tok.kind != Token::Kind::Eof) {
  2229. // Literals
  2230. switch (tok.kind) {
  2231. case Token::Kind::String: {
  2232. if (current_brace_level == 0 && current_bracket_level == 0) {
  2233. json_literal_start = tok.text;
  2234. add_json_literal(tmpl.content.c_str());
  2235. }
  2236. } break;
  2237. case Token::Kind::Number: {
  2238. if (current_brace_level == 0 && current_bracket_level == 0) {
  2239. json_literal_start = tok.text;
  2240. add_json_literal(tmpl.content.c_str());
  2241. }
  2242. } break;
  2243. case Token::Kind::LeftBracket: {
  2244. if (current_brace_level == 0 && current_bracket_level == 0) {
  2245. json_literal_start = tok.text;
  2246. }
  2247. current_bracket_level += 1;
  2248. } break;
  2249. case Token::Kind::LeftBrace: {
  2250. if (current_brace_level == 0 && current_bracket_level == 0) {
  2251. json_literal_start = tok.text;
  2252. }
  2253. current_brace_level += 1;
  2254. } break;
  2255. case Token::Kind::RightBracket: {
  2256. if (current_bracket_level == 0) {
  2257. throw_parser_error("unexpected ']'");
  2258. }
  2259. current_bracket_level -= 1;
  2260. if (current_brace_level == 0 && current_bracket_level == 0) {
  2261. add_json_literal(tmpl.content.c_str());
  2262. }
  2263. } break;
  2264. case Token::Kind::RightBrace: {
  2265. if (current_brace_level == 0) {
  2266. throw_parser_error("unexpected '}'");
  2267. }
  2268. current_brace_level -= 1;
  2269. if (current_brace_level == 0 && current_bracket_level == 0) {
  2270. add_json_literal(tmpl.content.c_str());
  2271. }
  2272. } break;
  2273. case Token::Kind::Id: {
  2274. get_peek_token();
  2275. // Json Literal
  2276. if (tok.text == static_cast<decltype(tok.text)>("true") || tok.text == static_cast<decltype(tok.text)>("false") || tok.text == static_cast<decltype(tok.text)>("null")) {
  2277. if (current_brace_level == 0 && current_bracket_level == 0) {
  2278. json_literal_start = tok.text;
  2279. add_json_literal(tmpl.content.c_str());
  2280. }
  2281. // Operator
  2282. } else if (tok.text == "and" || tok.text == "or" || tok.text == "in" || tok.text == "not") {
  2283. goto parse_operator;
  2284. // Functions
  2285. } else if (peek_tok.kind == Token::Kind::LeftParen) {
  2286. operator_stack.emplace(std::make_shared<FunctionNode>(static_cast<std::string>(tok.text), tok.text.data() - tmpl.content.c_str()));
  2287. function_stack.emplace(operator_stack.top().get(), current_paren_level);
  2288. // Variables
  2289. } else {
  2290. current_expression_list->rpn_output.emplace_back(std::make_shared<JsonNode>(static_cast<std::string>(tok.text), tok.text.data() - tmpl.content.c_str()));
  2291. }
  2292. // Operators
  2293. } break;
  2294. case Token::Kind::Equal:
  2295. case Token::Kind::NotEqual:
  2296. case Token::Kind::GreaterThan:
  2297. case Token::Kind::GreaterEqual:
  2298. case Token::Kind::LessThan:
  2299. case Token::Kind::LessEqual:
  2300. case Token::Kind::Plus:
  2301. case Token::Kind::Minus:
  2302. case Token::Kind::Times:
  2303. case Token::Kind::Slash:
  2304. case Token::Kind::Power:
  2305. case Token::Kind::Percent:
  2306. case Token::Kind::Dot: {
  2307. parse_operator:
  2308. FunctionStorage::Operation operation;
  2309. switch (tok.kind) {
  2310. case Token::Kind::Id: {
  2311. if (tok.text == "and") {
  2312. operation = FunctionStorage::Operation::And;
  2313. } else if (tok.text == "or") {
  2314. operation = FunctionStorage::Operation::Or;
  2315. } else if (tok.text == "in") {
  2316. operation = FunctionStorage::Operation::In;
  2317. } else if (tok.text == "not") {
  2318. operation = FunctionStorage::Operation::Not;
  2319. } else {
  2320. throw_parser_error("unknown operator in parser.");
  2321. }
  2322. } break;
  2323. case Token::Kind::Equal: {
  2324. operation = FunctionStorage::Operation::Equal;
  2325. } break;
  2326. case Token::Kind::NotEqual: {
  2327. operation = FunctionStorage::Operation::NotEqual;
  2328. } break;
  2329. case Token::Kind::GreaterThan: {
  2330. operation = FunctionStorage::Operation::Greater;
  2331. } break;
  2332. case Token::Kind::GreaterEqual: {
  2333. operation = FunctionStorage::Operation::GreaterEqual;
  2334. } break;
  2335. case Token::Kind::LessThan: {
  2336. operation = FunctionStorage::Operation::Less;
  2337. } break;
  2338. case Token::Kind::LessEqual: {
  2339. operation = FunctionStorage::Operation::LessEqual;
  2340. } break;
  2341. case Token::Kind::Plus: {
  2342. operation = FunctionStorage::Operation::Add;
  2343. } break;
  2344. case Token::Kind::Minus: {
  2345. operation = FunctionStorage::Operation::Subtract;
  2346. } break;
  2347. case Token::Kind::Times: {
  2348. operation = FunctionStorage::Operation::Multiplication;
  2349. } break;
  2350. case Token::Kind::Slash: {
  2351. operation = FunctionStorage::Operation::Division;
  2352. } break;
  2353. case Token::Kind::Power: {
  2354. operation = FunctionStorage::Operation::Power;
  2355. } break;
  2356. case Token::Kind::Percent: {
  2357. operation = FunctionStorage::Operation::Modulo;
  2358. } break;
  2359. case Token::Kind::Dot: {
  2360. operation = FunctionStorage::Operation::AtId;
  2361. } break;
  2362. default: {
  2363. throw_parser_error("unknown operator in parser.");
  2364. }
  2365. }
  2366. auto function_node = std::make_shared<FunctionNode>(operation, tok.text.data() - tmpl.content.c_str());
  2367. while (!operator_stack.empty() && ((operator_stack.top()->precedence > function_node->precedence) || (operator_stack.top()->precedence == function_node->precedence && function_node->associativity == FunctionNode::Associativity::Left)) && (operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft)) {
  2368. current_expression_list->rpn_output.emplace_back(operator_stack.top());
  2369. operator_stack.pop();
  2370. }
  2371. operator_stack.emplace(function_node);
  2372. } break;
  2373. case Token::Kind::Comma: {
  2374. if (current_brace_level == 0 && current_bracket_level == 0) {
  2375. if (function_stack.empty()) {
  2376. throw_parser_error("unexpected ','");
  2377. }
  2378. function_stack.top().first->number_args += 1;
  2379. }
  2380. } break;
  2381. case Token::Kind::Colon: {
  2382. if (current_brace_level == 0 && current_bracket_level == 0) {
  2383. throw_parser_error("unexpected ':'");
  2384. }
  2385. } break;
  2386. case Token::Kind::LeftParen: {
  2387. current_paren_level += 1;
  2388. operator_stack.emplace(std::make_shared<FunctionNode>(FunctionStorage::Operation::ParenLeft, tok.text.data() - tmpl.content.c_str()));
  2389. get_peek_token();
  2390. if (peek_tok.kind == Token::Kind::RightParen) {
  2391. if (!function_stack.empty() && function_stack.top().second == current_paren_level - 1) {
  2392. function_stack.top().first->number_args = 0;
  2393. }
  2394. }
  2395. } break;
  2396. case Token::Kind::RightParen: {
  2397. current_paren_level -= 1;
  2398. while (!operator_stack.empty() && operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft) {
  2399. current_expression_list->rpn_output.emplace_back(operator_stack.top());
  2400. operator_stack.pop();
  2401. }
  2402. if (!operator_stack.empty() && operator_stack.top()->operation == FunctionStorage::Operation::ParenLeft) {
  2403. operator_stack.pop();
  2404. }
  2405. if (!function_stack.empty() && function_stack.top().second == current_paren_level) {
  2406. auto func = function_stack.top().first;
  2407. auto function_data = function_storage.find_function(func->name, func->number_args);
  2408. if (function_data.operation == FunctionStorage::Operation::None) {
  2409. throw_parser_error("unknown function " + func->name);
  2410. }
  2411. func->operation = function_data.operation;
  2412. if (function_data.operation == FunctionStorage::Operation::Callback) {
  2413. func->callback = function_data.callback;
  2414. }
  2415. if (operator_stack.empty()) {
  2416. throw_parser_error("internal error at function " + func->name);
  2417. }
  2418. current_expression_list->rpn_output.emplace_back(operator_stack.top());
  2419. operator_stack.pop();
  2420. function_stack.pop();
  2421. }
  2422. }
  2423. default:
  2424. break;
  2425. }
  2426. get_next_token();
  2427. }
  2428. while (!operator_stack.empty()) {
  2429. current_expression_list->rpn_output.emplace_back(operator_stack.top());
  2430. operator_stack.pop();
  2431. }
  2432. return true;
  2433. }
  2434. bool parse_statement(Template &tmpl, Token::Kind closing, nonstd::string_view path) {
  2435. if (tok.kind != Token::Kind::Id) {
  2436. return false;
  2437. }
  2438. if (tok.text == static_cast<decltype(tok.text)>("if")) {
  2439. get_next_token();
  2440. auto if_statement_node = std::make_shared<IfStatementNode>(current_block, tok.text.data() - tmpl.content.c_str());
  2441. current_block->nodes.emplace_back(if_statement_node);
  2442. if_statement_stack.emplace(if_statement_node.get());
  2443. current_block = &if_statement_node->true_statement;
  2444. current_expression_list = &if_statement_node->condition;
  2445. if (!parse_expression(tmpl, closing)) {
  2446. return false;
  2447. }
  2448. } else if (tok.text == static_cast<decltype(tok.text)>("else")) {
  2449. if (if_statement_stack.empty()) {
  2450. throw_parser_error("else without matching if");
  2451. }
  2452. auto &if_statement_data = if_statement_stack.top();
  2453. get_next_token();
  2454. if_statement_data->has_false_statement = true;
  2455. current_block = &if_statement_data->false_statement;
  2456. // Chained else if
  2457. if (tok.kind == Token::Kind::Id && tok.text == static_cast<decltype(tok.text)>("if")) {
  2458. get_next_token();
  2459. auto if_statement_node = std::make_shared<IfStatementNode>(true, current_block, tok.text.data() - tmpl.content.c_str());
  2460. current_block->nodes.emplace_back(if_statement_node);
  2461. if_statement_stack.emplace(if_statement_node.get());
  2462. current_block = &if_statement_node->true_statement;
  2463. current_expression_list = &if_statement_node->condition;
  2464. if (!parse_expression(tmpl, closing)) {
  2465. return false;
  2466. }
  2467. }
  2468. } else if (tok.text == static_cast<decltype(tok.text)>("endif")) {
  2469. if (if_statement_stack.empty()) {
  2470. throw_parser_error("endif without matching if");
  2471. }
  2472. // Nested if statements
  2473. while (if_statement_stack.top()->is_nested) {
  2474. if_statement_stack.pop();
  2475. }
  2476. auto &if_statement_data = if_statement_stack.top();
  2477. get_next_token();
  2478. current_block = if_statement_data->parent;
  2479. if_statement_stack.pop();
  2480. } else if (tok.text == static_cast<decltype(tok.text)>("for")) {
  2481. get_next_token();
  2482. // options: for a in arr; for a, b in obj
  2483. if (tok.kind != Token::Kind::Id) {
  2484. throw_parser_error("expected id, got '" + tok.describe() + "'");
  2485. }
  2486. Token value_token = tok;
  2487. get_next_token();
  2488. // Object type
  2489. std::shared_ptr<ForStatementNode> for_statement_node;
  2490. if (tok.kind == Token::Kind::Comma) {
  2491. get_next_token();
  2492. if (tok.kind != Token::Kind::Id) {
  2493. throw_parser_error("expected id, got '" + tok.describe() + "'");
  2494. }
  2495. Token key_token = std::move(value_token);
  2496. value_token = tok;
  2497. get_next_token();
  2498. for_statement_node = std::make_shared<ForObjectStatementNode>(static_cast<std::string>(key_token.text), static_cast<std::string>(value_token.text), current_block, tok.text.data() - tmpl.content.c_str());
  2499. // Array type
  2500. } else {
  2501. for_statement_node = std::make_shared<ForArrayStatementNode>(static_cast<std::string>(value_token.text), current_block, tok.text.data() - tmpl.content.c_str());
  2502. }
  2503. current_block->nodes.emplace_back(for_statement_node);
  2504. for_statement_stack.emplace(for_statement_node.get());
  2505. current_block = &for_statement_node->body;
  2506. current_expression_list = &for_statement_node->condition;
  2507. if (tok.kind != Token::Kind::Id || tok.text != static_cast<decltype(tok.text)>("in")) {
  2508. throw_parser_error("expected 'in', got '" + tok.describe() + "'");
  2509. }
  2510. get_next_token();
  2511. if (!parse_expression(tmpl, closing)) {
  2512. return false;
  2513. }
  2514. } else if (tok.text == static_cast<decltype(tok.text)>("endfor")) {
  2515. if (for_statement_stack.empty()) {
  2516. throw_parser_error("endfor without matching for");
  2517. }
  2518. auto &for_statement_data = for_statement_stack.top();
  2519. get_next_token();
  2520. current_block = for_statement_data->parent;
  2521. for_statement_stack.pop();
  2522. } else if (tok.text == static_cast<decltype(tok.text)>("include")) {
  2523. get_next_token();
  2524. if (tok.kind != Token::Kind::String) {
  2525. throw_parser_error("expected string, got '" + tok.describe() + "'");
  2526. }
  2527. // Build the relative path
  2528. json json_name = json::parse(tok.text);
  2529. std::string pathname = static_cast<std::string>(path);
  2530. pathname += json_name.get_ref<const std::string &>();
  2531. if (pathname.compare(0, 2, "./") == 0) {
  2532. pathname.erase(0, 2);
  2533. }
  2534. // sys::path::remove_dots(pathname, true, sys::path::Style::posix);
  2535. if(config.include_scope_limit)
  2536. {
  2537. #ifdef _WIN32
  2538. if(pathname.find(":\\") != pathname.npos || pathname.find("..") != pathname.npos)
  2539. throw FileError("access denied when trying to include '" + pathname + "': out of scope");
  2540. #else
  2541. if(pathname.find("/") == 0 || pathname.find("..") != pathname.npos)
  2542. throw FileError("access denied when trying to include '" + pathname + "': out of scope");
  2543. #endif // _WIN32
  2544. if(config.include_scope.size() && pathname.find(config.include_scope) != 0)
  2545. throw FileError("access denied when trying to include '" + pathname + "': out of scope");
  2546. }
  2547. if (config.search_included_templates_in_files && template_storage.find(pathname) == template_storage.end()) {
  2548. auto include_template = Template(load_file(pathname));
  2549. template_storage.emplace(pathname, include_template);
  2550. parse_into_template(template_storage[pathname], pathname);
  2551. }
  2552. current_block->nodes.emplace_back(std::make_shared<IncludeStatementNode>(pathname, tok.text.data() - tmpl.content.c_str()));
  2553. get_next_token();
  2554. } else if (tok.text == static_cast<decltype(tok.text)>("set")) {
  2555. get_next_token();
  2556. if (tok.kind != Token::Kind::Id) {
  2557. throw_parser_error("expected variable name, got '" + tok.describe() + "'");
  2558. }
  2559. std::string key = static_cast<std::string>(tok.text);
  2560. get_next_token();
  2561. auto set_statement_node = std::make_shared<SetStatementNode>(key, tok.text.data() - tmpl.content.c_str());
  2562. current_block->nodes.emplace_back(set_statement_node);
  2563. current_expression_list = &set_statement_node->expression;
  2564. if (tok.text != static_cast<decltype(tok.text)>("=")) {
  2565. throw_parser_error("expected '=', got '" + tok.describe() + "'");
  2566. }
  2567. get_next_token();
  2568. if (!parse_expression(tmpl, closing)) {
  2569. return false;
  2570. }
  2571. } else {
  2572. return false;
  2573. }
  2574. return true;
  2575. }
  2576. void parse_into(Template &tmpl, nonstd::string_view path) {
  2577. lexer.start(tmpl.content);
  2578. current_block = &tmpl.root;
  2579. for (;;) {
  2580. get_next_token();
  2581. switch (tok.kind) {
  2582. case Token::Kind::Eof: {
  2583. if (!if_statement_stack.empty()) {
  2584. throw_parser_error("unmatched if");
  2585. }
  2586. if (!for_statement_stack.empty()) {
  2587. throw_parser_error("unmatched for");
  2588. }
  2589. } return;
  2590. case Token::Kind::Text: {
  2591. current_block->nodes.emplace_back(std::make_shared<TextNode>(tok.text.data() - tmpl.content.c_str(), tok.text.size()));
  2592. } break;
  2593. case Token::Kind::StatementOpen: {
  2594. get_next_token();
  2595. if (!parse_statement(tmpl, Token::Kind::StatementClose, path)) {
  2596. throw_parser_error("expected statement, got '" + tok.describe() + "'");
  2597. }
  2598. if (tok.kind != Token::Kind::StatementClose) {
  2599. throw_parser_error("expected statement close, got '" + tok.describe() + "'");
  2600. }
  2601. } break;
  2602. case Token::Kind::LineStatementOpen: {
  2603. get_next_token();
  2604. if (!parse_statement(tmpl, Token::Kind::LineStatementClose, path)) {
  2605. throw_parser_error("expected statement, got '" + tok.describe() + "'");
  2606. }
  2607. if (tok.kind != Token::Kind::LineStatementClose && tok.kind != Token::Kind::Eof) {
  2608. throw_parser_error("expected line statement close, got '" + tok.describe() + "'");
  2609. }
  2610. } break;
  2611. case Token::Kind::ExpressionOpen: {
  2612. get_next_token();
  2613. auto expression_list_node = std::make_shared<ExpressionListNode>(tok.text.data() - tmpl.content.c_str());
  2614. current_block->nodes.emplace_back(expression_list_node);
  2615. current_expression_list = expression_list_node.get();
  2616. if (!parse_expression(tmpl, Token::Kind::ExpressionClose)) {
  2617. throw_parser_error("expected expression, got '" + tok.describe() + "'");
  2618. }
  2619. if (tok.kind != Token::Kind::ExpressionClose) {
  2620. throw_parser_error("expected expression close, got '" + tok.describe() + "'");
  2621. }
  2622. } break;
  2623. case Token::Kind::CommentOpen: {
  2624. get_next_token();
  2625. if (tok.kind != Token::Kind::CommentClose) {
  2626. throw_parser_error("expected comment close, got '" + tok.describe() + "'");
  2627. }
  2628. } break;
  2629. default: {
  2630. throw_parser_error("unexpected token '" + tok.describe() + "'");
  2631. } break;
  2632. }
  2633. }
  2634. }
  2635. public:
  2636. explicit Parser(const ParserConfig &parser_config, const LexerConfig &lexer_config,
  2637. TemplateStorage &template_storage, const FunctionStorage &function_storage)
  2638. : config(parser_config), lexer(lexer_config), template_storage(template_storage), function_storage(function_storage) { }
  2639. Template parse(nonstd::string_view input, nonstd::string_view path) {
  2640. auto result = Template(static_cast<std::string>(input));
  2641. parse_into(result, path);
  2642. return result;
  2643. }
  2644. Template parse(nonstd::string_view input) {
  2645. return parse(input, "./");
  2646. }
  2647. void parse_into_template(Template& tmpl, nonstd::string_view filename) {
  2648. nonstd::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1);
  2649. // StringRef path = sys::path::parent_path(filename);
  2650. auto sub_parser = Parser(config, lexer.get_config(), template_storage, function_storage);
  2651. sub_parser.parse_into(tmpl, path);
  2652. }
  2653. std::string load_file(nonstd::string_view filename) {
  2654. std::ifstream file;
  2655. open_file_or_throw(static_cast<std::string>(filename), file);
  2656. std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
  2657. return text;
  2658. }
  2659. };
  2660. } // namespace inja
  2661. #endif // INCLUDE_INJA_PARSER_HPP_
  2662. // #include "renderer.hpp"
  2663. // Copyright (c) 2020 Pantor. All rights reserved.
  2664. #ifndef INCLUDE_INJA_RENDERER_HPP_
  2665. #define INCLUDE_INJA_RENDERER_HPP_
  2666. #include <algorithm>
  2667. #include <numeric>
  2668. #include <string>
  2669. #include <utility>
  2670. #include <vector>
  2671. #include <nlohmann/json.hpp>
  2672. // #include "config.hpp"
  2673. // #include "exceptions.hpp"
  2674. // #include "node.hpp"
  2675. // #include "template.hpp"
  2676. // #include "utils.hpp"
  2677. namespace inja {
  2678. /*!
  2679. * \brief Class for rendering a Template with data.
  2680. */
  2681. class Renderer : public NodeVisitor {
  2682. using Op = FunctionStorage::Operation;
  2683. const RenderConfig config;
  2684. const Template *current_template;
  2685. const TemplateStorage &template_storage;
  2686. const FunctionStorage &function_storage;
  2687. const json *json_input;
  2688. std::ostream *output_stream;
  2689. json json_additional_data;
  2690. json* current_loop_data = &json_additional_data["loop"];
  2691. std::vector<std::shared_ptr<json>> json_tmp_stack;
  2692. std::stack<const json*> json_eval_stack;
  2693. std::stack<const JsonNode*> not_found_stack;
  2694. bool truthy(const json* data) const {
  2695. if (data->is_boolean()) {
  2696. return data->get<bool>();
  2697. } else if (data->is_number()) {
  2698. return (*data != 0);
  2699. } else if (data->is_null()) {
  2700. return false;
  2701. }
  2702. return !data->empty();
  2703. }
  2704. void print_json(const std::shared_ptr<json> value) {
  2705. if (value->is_string()) {
  2706. *output_stream << value->get_ref<const json::string_t&>();
  2707. } else if (value->is_number_integer()) {
  2708. *output_stream << value->get<const json::number_integer_t>();
  2709. } else if (value->is_null()) {
  2710. } else {
  2711. *output_stream << value->dump();
  2712. }
  2713. }
  2714. const std::shared_ptr<json> eval_expression_list(const ExpressionListNode& expression_list) {
  2715. for (auto& expression : expression_list.rpn_output) {
  2716. expression->accept(*this);
  2717. }
  2718. if (json_eval_stack.empty()) {
  2719. throw_renderer_error("empty expression", expression_list);
  2720. } else if (json_eval_stack.size() != 1) {
  2721. throw_renderer_error("malformed expression", expression_list);
  2722. }
  2723. auto result = json_eval_stack.top();
  2724. json_eval_stack.pop();
  2725. if (!result) {
  2726. if (not_found_stack.empty()) {
  2727. throw_renderer_error("expression could not be evaluated", expression_list);
  2728. }
  2729. auto node = not_found_stack.top();
  2730. not_found_stack.pop();
  2731. throw_renderer_error("variable '" + static_cast<std::string>(node->name) + "' not found", *node);
  2732. }
  2733. return std::make_shared<json>(*result);
  2734. }
  2735. void throw_renderer_error(const std::string &message, const AstNode& node) {
  2736. SourceLocation loc = get_source_location(current_template->content, node.pos);
  2737. throw RenderError(message, loc);
  2738. }
  2739. template<size_t N, bool throw_not_found=true>
  2740. std::array<const json*, N> get_arguments(const AstNode& node) {
  2741. if (json_eval_stack.size() < N) {
  2742. throw_renderer_error("function needs " + std::to_string(N) + " variables, but has only found " + std::to_string(json_eval_stack.size()), node);
  2743. }
  2744. std::array<const json*, N> result;
  2745. for (size_t i = 0; i < N; i += 1) {
  2746. result[N - i - 1] = json_eval_stack.top();
  2747. json_eval_stack.pop();
  2748. if (!result[N - i - 1]) {
  2749. auto json_node = not_found_stack.top();
  2750. not_found_stack.pop();
  2751. if (throw_not_found) {
  2752. throw_renderer_error("variable '" + static_cast<std::string>(json_node->name) + "' not found", *json_node);
  2753. }
  2754. }
  2755. }
  2756. return result;
  2757. }
  2758. template<bool throw_not_found=true>
  2759. Arguments get_argument_vector(size_t N, const AstNode& node) {
  2760. Arguments result {N};
  2761. for (size_t i = 0; i < N; i += 1) {
  2762. result[N - i - 1] = json_eval_stack.top();
  2763. json_eval_stack.pop();
  2764. if (!result[N - i - 1]) {
  2765. auto json_node = not_found_stack.top();
  2766. not_found_stack.pop();
  2767. if (throw_not_found) {
  2768. throw_renderer_error("variable '" + static_cast<std::string>(json_node->name) + "' not found", *json_node);
  2769. }
  2770. }
  2771. }
  2772. return result;
  2773. }
  2774. void visit(const BlockNode& node) {
  2775. for (auto& n : node.nodes) {
  2776. n->accept(*this);
  2777. }
  2778. }
  2779. void visit(const TextNode& node) {
  2780. output_stream->write(current_template->content.c_str() + node.pos, node.length);
  2781. }
  2782. void visit(const ExpressionNode&) { }
  2783. void visit(const LiteralNode& node) {
  2784. json_eval_stack.push(&node.value);
  2785. }
  2786. void visit(const JsonNode& node) {
  2787. if (json_additional_data.contains(node.ptr)) {
  2788. json_eval_stack.push(&(json_additional_data[node.ptr]));
  2789. } else if (json_input->contains(node.ptr)) {
  2790. json_eval_stack.push(&(*json_input)[node.ptr]);
  2791. } else {
  2792. // Try to evaluate as a no-argument callback
  2793. auto function_data = function_storage.find_function(node.name, 0);
  2794. if (function_data.operation == FunctionStorage::Operation::Callback) {
  2795. Arguments empty_args {};
  2796. auto value = std::make_shared<json>(function_data.callback(empty_args));
  2797. json_tmp_stack.push_back(value);
  2798. json_eval_stack.push(value.get());
  2799. } else {
  2800. json_eval_stack.push(nullptr);
  2801. not_found_stack.emplace(&node);
  2802. }
  2803. }
  2804. }
  2805. void visit(const FunctionNode& node) {
  2806. std::shared_ptr<json> result_ptr;
  2807. switch (node.operation) {
  2808. case Op::Not: {
  2809. auto args = get_arguments<1>(node);
  2810. result_ptr = std::make_shared<json>(!truthy(args[0]));
  2811. json_tmp_stack.push_back(result_ptr);
  2812. json_eval_stack.push(result_ptr.get());
  2813. } break;
  2814. case Op::And: {
  2815. auto args = get_arguments<2>(node);
  2816. result_ptr = std::make_shared<json>(truthy(args[0]) && truthy(args[1]));
  2817. json_tmp_stack.push_back(result_ptr);
  2818. json_eval_stack.push(result_ptr.get());
  2819. } break;
  2820. case Op::Or: {
  2821. auto args = get_arguments<2>(node);
  2822. result_ptr = std::make_shared<json>(truthy(args[0]) || truthy(args[1]));
  2823. json_tmp_stack.push_back(result_ptr);
  2824. json_eval_stack.push(result_ptr.get());
  2825. } break;
  2826. case Op::In: {
  2827. auto args = get_arguments<2>(node);
  2828. result_ptr = std::make_shared<json>(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
  2829. json_tmp_stack.push_back(result_ptr);
  2830. json_eval_stack.push(result_ptr.get());
  2831. } break;
  2832. case Op::Equal: {
  2833. auto args = get_arguments<2>(node);
  2834. result_ptr = std::make_shared<json>(*args[0] == *args[1]);
  2835. json_tmp_stack.push_back(result_ptr);
  2836. json_eval_stack.push(result_ptr.get());
  2837. } break;
  2838. case Op::NotEqual: {
  2839. auto args = get_arguments<2>(node);
  2840. result_ptr = std::make_shared<json>(*args[0] != *args[1]);
  2841. json_tmp_stack.push_back(result_ptr);
  2842. json_eval_stack.push(result_ptr.get());
  2843. } break;
  2844. case Op::Greater: {
  2845. auto args = get_arguments<2>(node);
  2846. result_ptr = std::make_shared<json>(*args[0] > *args[1]);
  2847. json_tmp_stack.push_back(result_ptr);
  2848. json_eval_stack.push(result_ptr.get());
  2849. } break;
  2850. case Op::GreaterEqual: {
  2851. auto args = get_arguments<2>(node);
  2852. result_ptr = std::make_shared<json>(*args[0] >= *args[1]);
  2853. json_tmp_stack.push_back(result_ptr);
  2854. json_eval_stack.push(result_ptr.get());
  2855. } break;
  2856. case Op::Less: {
  2857. auto args = get_arguments<2>(node);
  2858. result_ptr = std::make_shared<json>(*args[0] < *args[1]);
  2859. json_tmp_stack.push_back(result_ptr);
  2860. json_eval_stack.push(result_ptr.get());
  2861. } break;
  2862. case Op::LessEqual: {
  2863. auto args = get_arguments<2>(node);
  2864. result_ptr = std::make_shared<json>(*args[0] <= *args[1]);
  2865. json_tmp_stack.push_back(result_ptr);
  2866. json_eval_stack.push(result_ptr.get());
  2867. } break;
  2868. case Op::Add: {
  2869. auto args = get_arguments<2>(node);
  2870. if (args[0]->is_string() && args[1]->is_string()) {
  2871. result_ptr = std::make_shared<json>(args[0]->get_ref<const std::string&>() + args[1]->get_ref<const std::string&>());
  2872. json_tmp_stack.push_back(result_ptr);
  2873. } else if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
  2874. result_ptr = std::make_shared<json>(args[0]->get<int>() + args[1]->get<int>());
  2875. json_tmp_stack.push_back(result_ptr);
  2876. } else {
  2877. result_ptr = std::make_shared<json>(args[0]->get<double>() + args[1]->get<double>());
  2878. json_tmp_stack.push_back(result_ptr);
  2879. }
  2880. json_eval_stack.push(result_ptr.get());
  2881. } break;
  2882. case Op::Subtract: {
  2883. auto args = get_arguments<2>(node);
  2884. if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
  2885. result_ptr = std::make_shared<json>(args[0]->get<int>() - args[1]->get<int>());
  2886. json_tmp_stack.push_back(result_ptr);
  2887. } else {
  2888. result_ptr = std::make_shared<json>(args[0]->get<double>() - args[1]->get<double>());
  2889. json_tmp_stack.push_back(result_ptr);
  2890. }
  2891. json_eval_stack.push(result_ptr.get());
  2892. } break;
  2893. case Op::Multiplication: {
  2894. auto args = get_arguments<2>(node);
  2895. if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
  2896. result_ptr = std::make_shared<json>(args[0]->get<int>() * args[1]->get<int>());
  2897. json_tmp_stack.push_back(result_ptr);
  2898. } else {
  2899. result_ptr = std::make_shared<json>(args[0]->get<double>() * args[1]->get<double>());
  2900. json_tmp_stack.push_back(result_ptr);
  2901. }
  2902. json_eval_stack.push(result_ptr.get());
  2903. } break;
  2904. case Op::Division: {
  2905. auto args = get_arguments<2>(node);
  2906. if (args[1]->get<double>() == 0) {
  2907. throw_renderer_error("division by zero", node);
  2908. }
  2909. result_ptr = std::make_shared<json>(args[0]->get<double>() / args[1]->get<double>());
  2910. json_tmp_stack.push_back(result_ptr);
  2911. json_eval_stack.push(result_ptr.get());
  2912. } break;
  2913. case Op::Power: {
  2914. auto args = get_arguments<2>(node);
  2915. if (args[0]->is_number_integer() && args[1]->get<int>() >= 0) {
  2916. int result = std::pow(args[0]->get<int>(), args[1]->get<int>());
  2917. result_ptr = std::make_shared<json>(std::move(result));
  2918. json_tmp_stack.push_back(result_ptr);
  2919. } else {
  2920. double result = std::pow(args[0]->get<double>(), args[1]->get<int>());
  2921. result_ptr = std::make_shared<json>(std::move(result));
  2922. json_tmp_stack.push_back(result_ptr);
  2923. }
  2924. json_eval_stack.push(result_ptr.get());
  2925. } break;
  2926. case Op::Modulo: {
  2927. auto args = get_arguments<2>(node);
  2928. result_ptr = std::make_shared<json>(args[0]->get<int>() % args[1]->get<int>());
  2929. json_tmp_stack.push_back(result_ptr);
  2930. json_eval_stack.push(result_ptr.get());
  2931. } break;
  2932. case Op::AtId: {
  2933. json_eval_stack.pop(); // Pop id nullptr
  2934. auto container = get_arguments<1, false>(node)[0];
  2935. if (not_found_stack.empty()) {
  2936. throw_renderer_error("could not find element with given name", node);
  2937. }
  2938. auto id_node = not_found_stack.top();
  2939. not_found_stack.pop();
  2940. json_eval_stack.push(&container->at(id_node->name));
  2941. } break;
  2942. case Op::At: {
  2943. auto args = get_arguments<2>(node);
  2944. json_eval_stack.push(&args[0]->at(args[1]->get<int>()));
  2945. } break;
  2946. case Op::Default: {
  2947. auto default_arg = get_arguments<1>(node)[0];
  2948. auto test_arg = get_arguments<1, false>(node)[0];
  2949. json_eval_stack.push(test_arg ? test_arg : default_arg);
  2950. } break;
  2951. case Op::DivisibleBy: {
  2952. auto args = get_arguments<2>(node);
  2953. int divisor = args[1]->get<int>();
  2954. result_ptr = std::make_shared<json>((divisor != 0) && (args[0]->get<int>() % divisor == 0));
  2955. json_tmp_stack.push_back(result_ptr);
  2956. json_eval_stack.push(result_ptr.get());
  2957. } break;
  2958. case Op::Even: {
  2959. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<int>() % 2 == 0);
  2960. json_tmp_stack.push_back(result_ptr);
  2961. json_eval_stack.push(result_ptr.get());
  2962. } break;
  2963. case Op::Exists: {
  2964. auto &&name = get_arguments<1>(node)[0]->get_ref<const std::string &>();
  2965. result_ptr = std::make_shared<json>(json_input->contains(json::json_pointer(JsonNode::convert_dot_to_json_ptr(name))));
  2966. json_tmp_stack.push_back(result_ptr);
  2967. json_eval_stack.push(result_ptr.get());
  2968. } break;
  2969. case Op::ExistsInObject: {
  2970. auto args = get_arguments<2>(node);
  2971. auto &&name = args[1]->get_ref<const std::string &>();
  2972. result_ptr = std::make_shared<json>(args[0]->find(name) != args[0]->end());
  2973. json_tmp_stack.push_back(result_ptr);
  2974. json_eval_stack.push(result_ptr.get());
  2975. } break;
  2976. case Op::First: {
  2977. auto result = &get_arguments<1>(node)[0]->front();
  2978. json_eval_stack.push(result);
  2979. } break;
  2980. case Op::Float: {
  2981. result_ptr = std::make_shared<json>(std::stod(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
  2982. json_tmp_stack.push_back(result_ptr);
  2983. json_eval_stack.push(result_ptr.get());
  2984. } break;
  2985. case Op::Int: {
  2986. result_ptr = std::make_shared<json>(std::stoi(get_arguments<1>(node)[0]->get_ref<const std::string &>()));
  2987. json_tmp_stack.push_back(result_ptr);
  2988. json_eval_stack.push(result_ptr.get());
  2989. } break;
  2990. case Op::Last: {
  2991. auto result = &get_arguments<1>(node)[0]->back();
  2992. json_eval_stack.push(result);
  2993. } break;
  2994. case Op::Length: {
  2995. auto val = get_arguments<1>(node)[0];
  2996. if (val->is_string()) {
  2997. result_ptr = std::make_shared<json>(val->get_ref<const std::string &>().length());
  2998. } else {
  2999. result_ptr = std::make_shared<json>(val->size());
  3000. }
  3001. json_tmp_stack.push_back(result_ptr);
  3002. json_eval_stack.push(result_ptr.get());
  3003. } break;
  3004. case Op::Lower: {
  3005. std::string result = get_arguments<1>(node)[0]->get<std::string>();
  3006. std::transform(result.begin(), result.end(), result.begin(), ::tolower);
  3007. result_ptr = std::make_shared<json>(std::move(result));
  3008. json_tmp_stack.push_back(result_ptr);
  3009. json_eval_stack.push(result_ptr.get());
  3010. } break;
  3011. case Op::Max: {
  3012. auto args = get_arguments<1>(node);
  3013. auto result = std::max_element(args[0]->begin(), args[0]->end());
  3014. json_eval_stack.push(&(*result));
  3015. } break;
  3016. case Op::Min: {
  3017. auto args = get_arguments<1>(node);
  3018. auto result = std::min_element(args[0]->begin(), args[0]->end());
  3019. json_eval_stack.push(&(*result));
  3020. } break;
  3021. case Op::Odd: {
  3022. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<int>() % 2 != 0);
  3023. json_tmp_stack.push_back(result_ptr);
  3024. json_eval_stack.push(result_ptr.get());
  3025. } break;
  3026. case Op::Range: {
  3027. std::vector<int> result(get_arguments<1>(node)[0]->get<int>());
  3028. std::iota(result.begin(), result.end(), 0);
  3029. result_ptr = std::make_shared<json>(std::move(result));
  3030. json_tmp_stack.push_back(result_ptr);
  3031. json_eval_stack.push(result_ptr.get());
  3032. } break;
  3033. case Op::Round: {
  3034. auto args = get_arguments<2>(node);
  3035. int precision = args[1]->get<int>();
  3036. double result = std::round(args[0]->get<double>() * std::pow(10.0, precision)) / std::pow(10.0, precision);
  3037. result_ptr = std::make_shared<json>(std::move(result));
  3038. json_tmp_stack.push_back(result_ptr);
  3039. json_eval_stack.push(result_ptr.get());
  3040. } break;
  3041. case Op::Sort: {
  3042. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->get<std::vector<json>>());
  3043. std::sort(result_ptr->begin(), result_ptr->end());
  3044. json_tmp_stack.push_back(result_ptr);
  3045. json_eval_stack.push(result_ptr.get());
  3046. } break;
  3047. case Op::Upper: {
  3048. std::string result = get_arguments<1>(node)[0]->get<std::string>();
  3049. std::transform(result.begin(), result.end(), result.begin(), ::toupper);
  3050. result_ptr = std::make_shared<json>(std::move(result));
  3051. json_tmp_stack.push_back(result_ptr);
  3052. json_eval_stack.push(result_ptr.get());
  3053. } break;
  3054. case Op::IsBoolean: {
  3055. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_boolean());
  3056. json_tmp_stack.push_back(result_ptr);
  3057. json_eval_stack.push(result_ptr.get());
  3058. } break;
  3059. case Op::IsNumber: {
  3060. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number());
  3061. json_tmp_stack.push_back(result_ptr);
  3062. json_eval_stack.push(result_ptr.get());
  3063. } break;
  3064. case Op::IsInteger: {
  3065. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number_integer());
  3066. json_tmp_stack.push_back(result_ptr);
  3067. json_eval_stack.push(result_ptr.get());
  3068. } break;
  3069. case Op::IsFloat: {
  3070. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_number_float());
  3071. json_tmp_stack.push_back(result_ptr);
  3072. json_eval_stack.push(result_ptr.get());
  3073. } break;
  3074. case Op::IsObject: {
  3075. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_object());
  3076. json_tmp_stack.push_back(result_ptr);
  3077. json_eval_stack.push(result_ptr.get());
  3078. } break;
  3079. case Op::IsArray: {
  3080. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_array());
  3081. json_tmp_stack.push_back(result_ptr);
  3082. json_eval_stack.push(result_ptr.get());
  3083. } break;
  3084. case Op::IsString: {
  3085. result_ptr = std::make_shared<json>(get_arguments<1>(node)[0]->is_string());
  3086. json_tmp_stack.push_back(result_ptr);
  3087. json_eval_stack.push(result_ptr.get());
  3088. } break;
  3089. case Op::Callback: {
  3090. auto args = get_argument_vector(node.number_args, node);
  3091. result_ptr = std::make_shared<json>(node.callback(args));
  3092. json_tmp_stack.push_back(result_ptr);
  3093. json_eval_stack.push(result_ptr.get());
  3094. } break;
  3095. case Op::ParenLeft:
  3096. case Op::ParenRight:
  3097. case Op::None:
  3098. break;
  3099. }
  3100. }
  3101. void visit(const ExpressionListNode& node) {
  3102. print_json(eval_expression_list(node));
  3103. }
  3104. void visit(const StatementNode&) { }
  3105. void visit(const ForStatementNode&) { }
  3106. void visit(const ForArrayStatementNode& node) {
  3107. auto result = eval_expression_list(node.condition);
  3108. if (!result->is_array()) {
  3109. throw_renderer_error("object must be an array", node);
  3110. }
  3111. if (!current_loop_data->empty()) {
  3112. auto tmp = *current_loop_data; // Because of clang-3
  3113. (*current_loop_data)["parent"] = std::move(tmp);
  3114. }
  3115. size_t index = 0;
  3116. (*current_loop_data)["is_first"] = true;
  3117. (*current_loop_data)["is_last"] = (result->size() <= 1);
  3118. for (auto it = result->begin(); it != result->end(); ++it) {
  3119. json_additional_data[static_cast<std::string>(node.value)] = *it;
  3120. (*current_loop_data)["index"] = index;
  3121. (*current_loop_data)["index1"] = index + 1;
  3122. if (index == 1) {
  3123. (*current_loop_data)["is_first"] = false;
  3124. }
  3125. if (index == result->size() - 1) {
  3126. (*current_loop_data)["is_last"] = true;
  3127. }
  3128. node.body.accept(*this);
  3129. ++index;
  3130. }
  3131. json_additional_data[static_cast<std::string>(node.value)].clear();
  3132. if (!(*current_loop_data)["parent"].empty()) {
  3133. auto tmp = (*current_loop_data)["parent"];
  3134. *current_loop_data = std::move(tmp);
  3135. } else {
  3136. current_loop_data = &json_additional_data["loop"];
  3137. }
  3138. }
  3139. void visit(const ForObjectStatementNode& node) {
  3140. auto result = eval_expression_list(node.condition);
  3141. if (!result->is_object()) {
  3142. throw_renderer_error("object must be an object", node);
  3143. }
  3144. if (!current_loop_data->empty()) {
  3145. (*current_loop_data)["parent"] = std::move(*current_loop_data);
  3146. }
  3147. size_t index = 0;
  3148. (*current_loop_data)["is_first"] = true;
  3149. (*current_loop_data)["is_last"] = (result->size() <= 1);
  3150. for (auto it = result->begin(); it != result->end(); ++it) {
  3151. json_additional_data[static_cast<std::string>(node.key)] = it.key();
  3152. json_additional_data[static_cast<std::string>(node.value)] = it.value();
  3153. (*current_loop_data)["index"] = index;
  3154. (*current_loop_data)["index1"] = index + 1;
  3155. if (index == 1) {
  3156. (*current_loop_data)["is_first"] = false;
  3157. }
  3158. if (index == result->size() - 1) {
  3159. (*current_loop_data)["is_last"] = true;
  3160. }
  3161. node.body.accept(*this);
  3162. ++index;
  3163. }
  3164. json_additional_data[static_cast<std::string>(node.key)].clear();
  3165. json_additional_data[static_cast<std::string>(node.value)].clear();
  3166. if (!(*current_loop_data)["parent"].empty()) {
  3167. *current_loop_data = std::move((*current_loop_data)["parent"]);
  3168. } else {
  3169. current_loop_data = &json_additional_data["loop"];
  3170. }
  3171. }
  3172. void visit(const IfStatementNode& node) {
  3173. auto result = eval_expression_list(node.condition);
  3174. if (truthy(result.get())) {
  3175. node.true_statement.accept(*this);
  3176. } else if (node.has_false_statement) {
  3177. node.false_statement.accept(*this);
  3178. }
  3179. }
  3180. void visit(const IncludeStatementNode& node) {
  3181. auto sub_renderer = Renderer(config, template_storage, function_storage);
  3182. auto included_template_it = template_storage.find(node.file);
  3183. if (included_template_it != template_storage.end()) {
  3184. sub_renderer.render_to(*output_stream, included_template_it->second, *json_input, &json_additional_data);
  3185. } else if (config.throw_at_missing_includes) {
  3186. throw_renderer_error("include '" + node.file + "' not found", node);
  3187. }
  3188. }
  3189. void visit(const SetStatementNode& node) {
  3190. json_additional_data[node.key] = *eval_expression_list(node.expression);
  3191. }
  3192. public:
  3193. Renderer(const RenderConfig& config, const TemplateStorage &template_storage, const FunctionStorage &function_storage)
  3194. : config(config), template_storage(template_storage), function_storage(function_storage) { }
  3195. void render_to(std::ostream &os, const Template &tmpl, const json &data, json *loop_data = nullptr) {
  3196. output_stream = &os;
  3197. current_template = &tmpl;
  3198. json_input = &data;
  3199. if (loop_data) {
  3200. json_additional_data = *loop_data;
  3201. current_loop_data = &json_additional_data["loop"];
  3202. }
  3203. current_template->root.accept(*this);
  3204. json_tmp_stack.clear();
  3205. }
  3206. };
  3207. } // namespace inja
  3208. #endif // INCLUDE_INJA_RENDERER_HPP_
  3209. // #include "string_view.hpp"
  3210. // #include "template.hpp"
  3211. // #include "utils.hpp"
  3212. namespace inja {
  3213. using json = nlohmann::json;
  3214. /*!
  3215. * \brief Class for changing the configuration.
  3216. */
  3217. class Environment {
  3218. std::string input_path;
  3219. std::string output_path;
  3220. LexerConfig lexer_config;
  3221. ParserConfig parser_config;
  3222. RenderConfig render_config;
  3223. FunctionStorage function_storage;
  3224. TemplateStorage template_storage;
  3225. public:
  3226. Environment() : Environment("") {}
  3227. explicit Environment(const std::string &global_path) : input_path(global_path), output_path(global_path) {}
  3228. Environment(const std::string &input_path, const std::string &output_path)
  3229. : input_path(input_path), output_path(output_path) {}
  3230. /// Sets the opener and closer for template statements
  3231. void set_statement(const std::string &open, const std::string &close) {
  3232. lexer_config.statement_open = open;
  3233. lexer_config.statement_open_no_lstrip = open + "+";
  3234. lexer_config.statement_open_force_lstrip = open + "-";
  3235. lexer_config.statement_close = close;
  3236. lexer_config.statement_close_force_rstrip = "-" + close;
  3237. lexer_config.update_open_chars();
  3238. }
  3239. /// Sets the opener for template line statements
  3240. void set_line_statement(const std::string &open) {
  3241. lexer_config.line_statement = open;
  3242. lexer_config.update_open_chars();
  3243. }
  3244. /// Sets the opener and closer for template expressions
  3245. void set_expression(const std::string &open, const std::string &close) {
  3246. lexer_config.expression_open = open;
  3247. lexer_config.expression_open_force_lstrip = open + "-";
  3248. lexer_config.expression_close = close;
  3249. lexer_config.expression_close_force_rstrip = "-" + close;
  3250. lexer_config.update_open_chars();
  3251. }
  3252. /// Sets the opener and closer for template comments
  3253. void set_comment(const std::string &open, const std::string &close) {
  3254. lexer_config.comment_open = open;
  3255. lexer_config.comment_close = close;
  3256. lexer_config.update_open_chars();
  3257. }
  3258. /// Sets whether to remove the first newline after a block
  3259. void set_trim_blocks(bool trim_blocks) {
  3260. lexer_config.trim_blocks = trim_blocks;
  3261. }
  3262. /// Sets whether to strip the spaces and tabs from the start of a line to a block
  3263. void set_lstrip_blocks(bool lstrip_blocks) {
  3264. lexer_config.lstrip_blocks = lstrip_blocks;
  3265. }
  3266. /// Sets the element notation syntax
  3267. void set_search_included_templates_in_files(bool search_in_files) {
  3268. parser_config.search_included_templates_in_files = search_in_files;
  3269. }
  3270. /// Sets whether a missing include will throw an error
  3271. void set_throw_at_missing_includes(bool will_throw) {
  3272. render_config.throw_at_missing_includes = will_throw;
  3273. }
  3274. Template parse(nonstd::string_view input) {
  3275. Parser parser(parser_config, lexer_config, template_storage, function_storage);
  3276. return parser.parse(input);
  3277. }
  3278. Template parse_template(const std::string &filename) {
  3279. Parser parser(parser_config, lexer_config, template_storage, function_storage);
  3280. auto result = Template(parser.load_file(input_path + static_cast<std::string>(filename)));
  3281. parser.parse_into_template(result, input_path + static_cast<std::string>(filename));
  3282. return result;
  3283. }
  3284. Template parse_file(const std::string &filename) {
  3285. return parse_template(filename);
  3286. }
  3287. std::string render(nonstd::string_view input, const json &data) { return render(parse(input), data); }
  3288. std::string render(const Template &tmpl, const json &data) {
  3289. std::stringstream os;
  3290. render_to(os, tmpl, data);
  3291. return os.str();
  3292. }
  3293. std::string render_file(const std::string &filename, const json &data) {
  3294. return render(parse_template(filename), data);
  3295. }
  3296. std::string render_file_with_json_file(const std::string &filename, const std::string &filename_data) {
  3297. const json data = load_json(filename_data);
  3298. return render_file(filename, data);
  3299. }
  3300. void write(const std::string &filename, const json &data, const std::string &filename_out) {
  3301. std::ofstream file(output_path + filename_out);
  3302. file << render_file(filename, data);
  3303. file.close();
  3304. }
  3305. void write(const Template &temp, const json &data, const std::string &filename_out) {
  3306. std::ofstream file(output_path + filename_out);
  3307. file << render(temp, data);
  3308. file.close();
  3309. }
  3310. void write_with_json_file(const std::string &filename, const std::string &filename_data,
  3311. const std::string &filename_out) {
  3312. const json data = load_json(filename_data);
  3313. write(filename, data, filename_out);
  3314. }
  3315. void write_with_json_file(const Template &temp, const std::string &filename_data, const std::string &filename_out) {
  3316. const json data = load_json(filename_data);
  3317. write(temp, data, filename_out);
  3318. }
  3319. std::ostream &render_to(std::ostream &os, const Template &tmpl, const json &data) {
  3320. Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data);
  3321. return os;
  3322. }
  3323. std::string load_file(const std::string &filename) {
  3324. Parser parser(parser_config, lexer_config, template_storage, function_storage);
  3325. return parser.load_file(input_path + filename);
  3326. }
  3327. json load_json(const std::string &filename) {
  3328. std::ifstream file;
  3329. open_file_or_throw(input_path + filename, file);
  3330. json j;
  3331. file >> j;
  3332. return j;
  3333. }
  3334. /*!
  3335. @brief Adds a variadic callback
  3336. */
  3337. void add_callback(const std::string &name, const CallbackFunction &callback) {
  3338. add_callback(name, -1, callback);
  3339. }
  3340. /*!
  3341. @brief Adds a variadic void callback
  3342. */
  3343. void add_void_callback(const std::string &name, const VoidCallbackFunction &callback) {
  3344. add_void_callback(name, -1, callback);
  3345. }
  3346. /*!
  3347. @brief Adds a callback with given number or arguments
  3348. */
  3349. void add_callback(const std::string &name, int num_args, const CallbackFunction &callback) {
  3350. function_storage.add_callback(name, num_args, callback);
  3351. }
  3352. /*!
  3353. @brief Adds a void callback with given number or arguments
  3354. */
  3355. void add_void_callback(const std::string &name, int num_args, const VoidCallbackFunction &callback) {
  3356. function_storage.add_callback(name, num_args, [callback](Arguments& args) { callback(args); return json(); });
  3357. }
  3358. /** Includes a template with a given name into the environment.
  3359. * Then, a template can be rendered in another template using the
  3360. * include "<name>" syntax.
  3361. */
  3362. void include_template(const std::string &name, const Template &tmpl) {
  3363. template_storage[name] = tmpl;
  3364. }
  3365. };
  3366. /*!
  3367. @brief render with default settings to a string
  3368. */
  3369. inline std::string render(nonstd::string_view input, const json &data) {
  3370. return Environment().render(input, data);
  3371. }
  3372. /*!
  3373. @brief render with default settings to the given output stream
  3374. */
  3375. inline void render_to(std::ostream &os, nonstd::string_view input, const json &data) {
  3376. Environment env;
  3377. env.render_to(os, env.parse(input), data);
  3378. }
  3379. } // namespace inja
  3380. #endif // INCLUDE_INJA_ENVIRONMENT_HPP_
  3381. // #include "exceptions.hpp"
  3382. // #include "parser.hpp"
  3383. // #include "renderer.hpp"
  3384. // #include "string_view.hpp"
  3385. // #include "template.hpp"
  3386. #endif // INCLUDE_INJA_INJA_HPP_