FixedString.h 102 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. // @author: Eric Niebler (eniebler)
  17. // Fixed-size string type, for constexpr string handling.
  18. #pragma once
  19. #include <cassert>
  20. #include <cstddef>
  21. #include <initializer_list>
  22. #include <iosfwd>
  23. #include <stdexcept>
  24. #include <string>
  25. #include <type_traits>
  26. #include <utility>
  27. #include <folly/ConstexprMath.h>
  28. #include <folly/Portability.h>
  29. #include <folly/Range.h>
  30. #include <folly/Utility.h>
  31. #include <folly/lang/Exception.h>
  32. #include <folly/lang/Ordering.h>
  33. #include <folly/portability/Constexpr.h>
  34. namespace folly {
  35. template <class Char, std::size_t N>
  36. class BasicFixedString;
  37. template <std::size_t N>
  38. using FixedString = BasicFixedString<char, N>;
  39. namespace detail {
  40. namespace fixedstring {
  41. // This is a template so that the class static npos can be defined in the
  42. // header.
  43. template <class = void>
  44. struct FixedStringBase_ {
  45. static constexpr std::size_t npos = static_cast<std::size_t>(-1);
  46. };
  47. template <class Void>
  48. constexpr std::size_t FixedStringBase_<Void>::npos;
  49. using FixedStringBase = FixedStringBase_<>;
  50. // Intentionally NOT constexpr. By making this not constexpr, we make
  51. // checkOverflow below ill-formed in a constexpr context when the condition
  52. // it's testing for fails. In this way, precondition violations are reported
  53. // at compile-time instead of at runtime.
  54. [[noreturn]] inline void assertOutOfBounds() {
  55. assert(!"Array index out of bounds in BasicFixedString");
  56. throw_exception<std::out_of_range>(
  57. "Array index out of bounds in BasicFixedString");
  58. }
  59. constexpr std::size_t checkOverflow(std::size_t i, std::size_t max) {
  60. return i <= max ? i : (void(assertOutOfBounds()), max);
  61. }
  62. constexpr std::size_t checkOverflowOrNpos(std::size_t i, std::size_t max) {
  63. return i == FixedStringBase::npos
  64. ? max
  65. : (i <= max ? i : (void(assertOutOfBounds()), max));
  66. }
  67. // Intentionally NOT constexpr. See note above for assertOutOfBounds
  68. [[noreturn]] inline void assertNotNullTerminated() noexcept {
  69. assert(!"Non-null terminated string used to initialize a BasicFixedString");
  70. std::terminate(); // Fail hard, fail fast.
  71. }
  72. // Parsing help for human readers: the following is a constexpr noexcept
  73. // function that accepts a reference to an array as a parameter and returns
  74. // a reference to the same array.
  75. template <class Char, std::size_t N>
  76. constexpr const Char (&checkNullTerminated(const Char (&a)[N]) noexcept)[N] {
  77. // Strange decltype(a)(a) used to make MSVC happy.
  78. return a[N - 1u] == Char(0)
  79. #ifndef NDEBUG
  80. // In Debug mode, guard against embedded nulls:
  81. && N - 1u == folly::detail::constexpr_strlen_internal(a, 0u)
  82. #endif
  83. ? decltype(a)(a)
  84. : (assertNotNullTerminated(), decltype(a)(a));
  85. }
  86. // Rather annoyingly, GCC's -Warray-bounds warning issues false positives for
  87. // this code. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971
  88. #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
  89. #pragma GCC diagnostic push
  90. #pragma GCC diagnostic ignored "-Warray-bounds"
  91. #endif
  92. template <class Left, class Right>
  93. constexpr ordering compare_(
  94. const Left& left,
  95. std::size_t left_pos,
  96. std::size_t left_size,
  97. const Right& right,
  98. std::size_t right_pos,
  99. std::size_t right_size) noexcept {
  100. return left_pos == left_size
  101. ? (right_pos == right_size ? ordering::eq : ordering::lt)
  102. : (right_pos == right_size ? ordering::gt
  103. : (left[left_pos] < right[right_pos]
  104. ? ordering::lt
  105. : (left[left_pos] > right[right_pos]
  106. ? ordering::gt
  107. : fixedstring::compare_(
  108. left,
  109. left_pos + 1u,
  110. left_size,
  111. right,
  112. right_pos + 1u,
  113. right_size))));
  114. }
  115. template <class Left, class Right>
  116. constexpr bool equal_(
  117. const Left& left,
  118. std::size_t left_size,
  119. const Right& right,
  120. std::size_t right_size) noexcept {
  121. return left_size == right_size &&
  122. ordering::eq == compare_(left, 0u, left_size, right, 0u, right_size);
  123. }
  124. template <class Char, class Left, class Right>
  125. constexpr Char char_at_(
  126. const Left& left,
  127. std::size_t left_count,
  128. const Right& right,
  129. std::size_t right_count,
  130. std::size_t i) noexcept {
  131. return i < left_count
  132. ? left[i]
  133. : i < (left_count + right_count) ? right[i - left_count] : Char(0);
  134. }
  135. template <class Char, class Left, class Right>
  136. constexpr Char char_at_(
  137. const Left& left,
  138. std::size_t left_size,
  139. std::size_t left_pos,
  140. std::size_t left_count,
  141. const Right& right,
  142. std::size_t right_pos,
  143. std::size_t right_count,
  144. std::size_t i) noexcept {
  145. return i < left_pos
  146. ? left[i]
  147. : (i < right_count + left_pos ? right[i - left_pos + right_pos]
  148. : (i < left_size - left_count + right_count
  149. ? left[i - right_count + left_count]
  150. : Char(0)));
  151. }
  152. template <class Left, class Right>
  153. constexpr bool find_at_(
  154. const Left& left,
  155. const Right& right,
  156. std::size_t pos,
  157. std::size_t count) noexcept {
  158. return 0u == count ||
  159. (left[pos + count - 1u] == right[count - 1u] &&
  160. find_at_(left, right, pos, count - 1u));
  161. }
  162. template <class Char, class Right>
  163. constexpr bool
  164. find_one_of_at_(Char ch, const Right& right, std::size_t pos) noexcept {
  165. return 0u != pos &&
  166. (ch == right[pos - 1u] || find_one_of_at_(ch, right, pos - 1u));
  167. }
  168. template <class Left, class Right>
  169. constexpr std::size_t find_(
  170. const Left& left,
  171. std::size_t left_size,
  172. const Right& right,
  173. std::size_t pos,
  174. std::size_t count) noexcept {
  175. return find_at_(left, right, pos, count) ? pos
  176. : left_size <= pos + count
  177. ? FixedStringBase::npos
  178. : find_(left, left_size, right, pos + 1u, count);
  179. }
  180. template <class Left, class Right>
  181. constexpr std::size_t rfind_(
  182. const Left& left,
  183. const Right& right,
  184. std::size_t pos,
  185. std::size_t count) noexcept {
  186. return find_at_(left, right, pos, count)
  187. ? pos
  188. : 0u == pos ? FixedStringBase::npos
  189. : rfind_(left, right, pos - 1u, count);
  190. }
  191. template <class Left, class Right>
  192. constexpr std::size_t find_first_of_(
  193. const Left& left,
  194. std::size_t left_size,
  195. const Right& right,
  196. std::size_t pos,
  197. std::size_t count) noexcept {
  198. return find_one_of_at_(left[pos], right, count) ? pos
  199. : left_size <= pos + 1u
  200. ? FixedStringBase::npos
  201. : find_first_of_(left, left_size, right, pos + 1u, count);
  202. }
  203. template <class Left, class Right>
  204. constexpr std::size_t find_first_not_of_(
  205. const Left& left,
  206. std::size_t left_size,
  207. const Right& right,
  208. std::size_t pos,
  209. std::size_t count) noexcept {
  210. return !find_one_of_at_(left[pos], right, count) ? pos
  211. : left_size <= pos + 1u
  212. ? FixedStringBase::npos
  213. : find_first_not_of_(left, left_size, right, pos + 1u, count);
  214. }
  215. template <class Left, class Right>
  216. constexpr std::size_t find_last_of_(
  217. const Left& left,
  218. const Right& right,
  219. std::size_t pos,
  220. std::size_t count) noexcept {
  221. return find_one_of_at_(left[pos], right, count)
  222. ? pos
  223. : 0u == pos ? FixedStringBase::npos
  224. : find_last_of_(left, right, pos - 1u, count);
  225. }
  226. template <class Left, class Right>
  227. constexpr std::size_t find_last_not_of_(
  228. const Left& left,
  229. const Right& right,
  230. std::size_t pos,
  231. std::size_t count) noexcept {
  232. return !find_one_of_at_(left[pos], right, count)
  233. ? pos
  234. : 0u == pos ? FixedStringBase::npos
  235. : find_last_not_of_(left, right, pos - 1u, count);
  236. }
  237. struct Helper {
  238. template <class Char, class Left, class Right, std::size_t... Is>
  239. static constexpr BasicFixedString<Char, sizeof...(Is)> concat_(
  240. const Left& left,
  241. std::size_t left_count,
  242. const Right& right,
  243. std::size_t right_count,
  244. folly::index_sequence<Is...> is) noexcept {
  245. return {left, left_count, right, right_count, is};
  246. }
  247. template <class Char, class Left, class Right, std::size_t... Is>
  248. static constexpr BasicFixedString<Char, sizeof...(Is)> replace_(
  249. const Left& left,
  250. std::size_t left_size,
  251. std::size_t left_pos,
  252. std::size_t left_count,
  253. const Right& right,
  254. std::size_t right_pos,
  255. std::size_t right_count,
  256. folly::index_sequence<Is...> is) noexcept {
  257. return {left,
  258. left_size,
  259. left_pos,
  260. left_count,
  261. right,
  262. right_pos,
  263. right_count,
  264. is};
  265. }
  266. template <class Char, std::size_t N>
  267. static constexpr const Char (
  268. &data_(const BasicFixedString<Char, N>& that) noexcept)[N + 1u] {
  269. return that.data_;
  270. }
  271. };
  272. #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4
  273. #pragma GCC diagnostic pop
  274. #endif
  275. template <class T>
  276. FOLLY_CPP14_CONSTEXPR void constexpr_swap(T& a, T& b) noexcept(
  277. noexcept(a = T(std::move(a)))) {
  278. T tmp((std::move(a)));
  279. a = std::move(b);
  280. b = std::move(tmp);
  281. }
  282. // For constexpr reverse iteration over a BasicFixedString
  283. template <class T>
  284. struct ReverseIterator {
  285. private:
  286. T* p_ = nullptr;
  287. struct dummy_ {
  288. T* p_ = nullptr;
  289. };
  290. using other = typename std::conditional<
  291. std::is_const<T>::value,
  292. ReverseIterator<typename std::remove_const<T>::type>,
  293. dummy_>::type;
  294. public:
  295. using value_type = typename std::remove_const<T>::type;
  296. using reference = T&;
  297. using pointer = T*;
  298. using difference_type = std::ptrdiff_t;
  299. using iterator_category = std::random_access_iterator_tag;
  300. constexpr ReverseIterator() = default;
  301. constexpr ReverseIterator(const ReverseIterator&) = default;
  302. FOLLY_CPP14_CONSTEXPR ReverseIterator& operator=(const ReverseIterator&) =
  303. default;
  304. constexpr explicit ReverseIterator(T* p) noexcept : p_(p) {}
  305. constexpr /* implicit */ ReverseIterator(const other& that) noexcept
  306. : p_(that.p_) {}
  307. friend constexpr bool operator==(
  308. ReverseIterator a,
  309. ReverseIterator b) noexcept {
  310. return a.p_ == b.p_;
  311. }
  312. friend constexpr bool operator!=(
  313. ReverseIterator a,
  314. ReverseIterator b) noexcept {
  315. return !(a == b);
  316. }
  317. constexpr reference operator*() const {
  318. return *(p_ - 1);
  319. }
  320. FOLLY_CPP14_CONSTEXPR ReverseIterator& operator++() noexcept {
  321. --p_;
  322. return *this;
  323. }
  324. FOLLY_CPP14_CONSTEXPR ReverseIterator operator++(int) noexcept {
  325. auto tmp(*this);
  326. --p_;
  327. return tmp;
  328. }
  329. FOLLY_CPP14_CONSTEXPR ReverseIterator& operator--() noexcept {
  330. ++p_;
  331. return *this;
  332. }
  333. FOLLY_CPP14_CONSTEXPR ReverseIterator operator--(int) noexcept {
  334. auto tmp(*this);
  335. ++p_;
  336. return tmp;
  337. }
  338. FOLLY_CPP14_CONSTEXPR ReverseIterator& operator+=(std::ptrdiff_t i) noexcept {
  339. p_ -= i;
  340. return *this;
  341. }
  342. friend constexpr ReverseIterator operator+(
  343. std::ptrdiff_t i,
  344. ReverseIterator that) noexcept {
  345. return ReverseIterator{that.p_ - i};
  346. }
  347. friend constexpr ReverseIterator operator+(
  348. ReverseIterator that,
  349. std::ptrdiff_t i) noexcept {
  350. return ReverseIterator{that.p_ - i};
  351. }
  352. FOLLY_CPP14_CONSTEXPR ReverseIterator& operator-=(std::ptrdiff_t i) noexcept {
  353. p_ += i;
  354. return *this;
  355. }
  356. friend constexpr ReverseIterator operator-(
  357. ReverseIterator that,
  358. std::ptrdiff_t i) noexcept {
  359. return ReverseIterator{that.p_ + i};
  360. }
  361. friend constexpr std::ptrdiff_t operator-(
  362. ReverseIterator a,
  363. ReverseIterator b) noexcept {
  364. return b.p_ - a.p_;
  365. }
  366. constexpr reference operator[](std::ptrdiff_t i) const noexcept {
  367. return *(*this + i);
  368. }
  369. };
  370. } // namespace fixedstring
  371. } // namespace detail
  372. // Defined in folly/hash/Hash.h
  373. std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
  374. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
  375. * \class BasicFixedString
  376. *
  377. * \tparam Char The character type. Must be a scalar type.
  378. * \tparam N The capacity and max size of string instances of this type.
  379. *
  380. * \brief A class for holding up to `N` characters of type `Char` that is
  381. * amenable to `constexpr` string manipulation. It is guaranteed to not
  382. * perform any dynamic allocation.
  383. *
  384. * `BasicFixedString` is a `std::string` work-alike that stores characters in an
  385. * internal buffer. It has minor interface differences that make it easy to work
  386. * with strings in a `constexpr` context.
  387. *
  388. * \par Example:
  389. * \par
  390. * \code
  391. * constexpr auto hello = makeFixedString("hello"); // a FixedString<5>
  392. * constexpr auto world = makeFixedString("world"); // a FixedString<5>
  393. * constexpr auto hello_world = hello + ' ' + world + '!'; // a FixedString<12>
  394. * static_assert(hello_world == "hello world!", "neato!");
  395. * \endcode
  396. * \par
  397. * `FixedString<N>` is an alias for `BasicFixedString<char, N>`.
  398. *
  399. * \par Constexpr and In-place Mutation
  400. * \par
  401. * On a C++14 compiler, `BasicFixedString` supports the full `std::string`
  402. * interface as `constexpr` member functions. On a C++11 compiler, the mutating
  403. * members are not `constexpr`, but non-mutating alternatives, which create a
  404. * new string, can be used instead. For example, instead of this:
  405. * \par
  406. * \code
  407. * constexpr FixedString<10> replace_example_cpp14() {
  408. * FixedString<10> test{"****"};
  409. * test.replace(1, 2, "!!!!");
  410. * return test; // returns "*!!!!*"
  411. * }
  412. * \endcode
  413. * \par
  414. * You might write this instead:
  415. * \par
  416. * \code
  417. * constexpr FixedString<10> replace_example_cpp11() {
  418. * // GNU compilers have an extension that make it possible to create
  419. * // FixedString objects with a `""_fs` user-defined literal.
  420. * using namespace folly;
  421. * return makeFixedString("****").creplace(1, 2, "!!!!"); // "*!!!!*"
  422. * }
  423. * \endcode
  424. *
  425. * \par User-defined Literals
  426. * Instead of using the `folly::makeFixedString` helper function, you can use
  427. * a user-defined literal to make `FixedString` instances. The UDL feature of
  428. * C++ has some limitations that make this less than ideal; you must tell the
  429. * compiler roughly how many characters are in the string. The suffixes `_fs4`,
  430. * `_fs8`, `_fs16`, `_fs32`, `_fs64`, and `_fs128` exist to create instances
  431. * of types `FixedString<4>`, `FixedString<8>`, etc. For example:
  432. * \par
  433. * \code
  434. * using namespace folly::string_literals;
  435. * constexpr auto hello = "hello"_fs8; // A FixedString<8> containing "hello"
  436. * \endcode
  437. * \par
  438. * See Error Handling below for what to expect when you try to exceed the
  439. * capacity of a `FixedString` by storing too many characters in it.
  440. * \par
  441. * If your compiler supports GNU extensions, there is one additional suffix you
  442. * can use: `_fs`. This suffix always creates `FixedString` objects of exactly
  443. * the right size. For example:
  444. * \par
  445. * \code
  446. * using namespace folly::string_literals;
  447. * // NOTE: Only works on compilers with GNU extensions enabled. Clang and
  448. * // gcc support this (-Wgnu-string-literal-operator-template):
  449. * constexpr auto hello = "hello"_fs; // A FixedString<5> containing "hello"
  450. * \endcode
  451. *
  452. * \par Error Handling:
  453. * The capacity of a `BasicFixedString` is set at compile time. When the user
  454. * asks the string to exceed its capacity, one of three things will happen,
  455. * depending on the context:
  456. *\par
  457. * -# If the attempt is made while evaluating a constant expression, the
  458. * program will fail to compile.
  459. * -# Otherwise, if the program is being run in debug mode, it will `assert`.
  460. * -# Otherwise, the failed operation will throw a `std::out_of_range`
  461. * exception.
  462. *\par
  463. * This is also the case if an invalid offset is passed to any member function,
  464. * or if `pop_back` or `cpop_back` is called on an empty `BasicFixedString`.
  465. *
  466. * Member functions documented as having preconditions will assert in Debug
  467. * mode (`!defined(NDEBUG)`) on precondition failures. Those documented with
  468. * \b Throws clauses will throw the specified exception on failure. Those with
  469. * both a precondition and a \b Throws clause will assert in Debug and throw
  470. * in Release mode.
  471. */
  472. template <class Char, std::size_t N>
  473. class BasicFixedString : private detail::fixedstring::FixedStringBase {
  474. private:
  475. template <class, std::size_t>
  476. friend class BasicFixedString;
  477. friend struct detail::fixedstring::Helper;
  478. // FUTURE: use constexpr_log2 to fold instantiations of BasicFixedString
  479. // together. All BasicFixedString<C, N> instantiations could share the
  480. // implementation of BasicFixedString<C, M>, where M is the next highest power
  481. // of 2 after N.
  482. //
  483. // Also, because of alignment of the data_ and size_ members, N should never
  484. // be smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the
  485. // null terminator). OR, create a specialization for BasicFixedString<C, 0u>
  486. // that does not have a size_ member, since it is unnecessary.
  487. Char data_[N + 1u]; // +1 for the null terminator
  488. std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N.
  489. using Indices = folly::make_index_sequence<N>;
  490. template <class That, std::size_t... Is>
  491. constexpr BasicFixedString(
  492. const That& that,
  493. std::size_t size,
  494. folly::index_sequence<Is...>,
  495. std::size_t pos = 0,
  496. std::size_t count = npos) noexcept
  497. : data_{(Is < (size - pos) && Is < count ? that[Is + pos] : Char(0))...,
  498. Char(0)},
  499. size_{folly::constexpr_min(size - pos, count)} {}
  500. template <std::size_t... Is>
  501. constexpr BasicFixedString(
  502. std::size_t count,
  503. Char ch,
  504. folly::index_sequence<Is...>) noexcept
  505. : data_{((Is < count) ? ch : Char(0))..., Char(0)}, size_{count} {}
  506. // Concatenation constructor
  507. template <class Left, class Right, std::size_t... Is>
  508. constexpr BasicFixedString(
  509. const Left& left,
  510. std::size_t left_size,
  511. const Right& right,
  512. std::size_t right_size,
  513. folly::index_sequence<Is...>) noexcept
  514. : data_{detail::fixedstring::char_at_<Char>(
  515. left,
  516. left_size,
  517. right,
  518. right_size,
  519. Is)...,
  520. Char(0)},
  521. size_{left_size + right_size} {}
  522. // Replace constructor
  523. template <class Left, class Right, std::size_t... Is>
  524. constexpr BasicFixedString(
  525. const Left& left,
  526. std::size_t left_size,
  527. std::size_t left_pos,
  528. std::size_t left_count,
  529. const Right& right,
  530. std::size_t right_pos,
  531. std::size_t right_count,
  532. folly::index_sequence<Is...>) noexcept
  533. : data_{detail::fixedstring::char_at_<Char>(
  534. left,
  535. left_size,
  536. left_pos,
  537. left_count,
  538. right,
  539. right_pos,
  540. right_count,
  541. Is)...,
  542. Char(0)},
  543. size_{left_size - left_count + right_count} {}
  544. public:
  545. using size_type = std::size_t;
  546. using difference_type = std::ptrdiff_t;
  547. using reference = Char&;
  548. using const_reference = const Char&;
  549. using pointer = Char*;
  550. using const_pointer = const Char*;
  551. using iterator = Char*;
  552. using const_iterator = const Char*;
  553. using reverse_iterator = detail::fixedstring::ReverseIterator<Char>;
  554. using const_reverse_iterator =
  555. detail::fixedstring::ReverseIterator<const Char>;
  556. using detail::fixedstring::FixedStringBase::npos;
  557. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  558. * Default construct
  559. * \post `size() == 0`
  560. * \post `at(0) == Char(0)`
  561. */
  562. constexpr BasicFixedString() : data_{}, size_{} {}
  563. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  564. * Copy construct
  565. * \post `size() == that.size()`
  566. * \post `0 == strncmp(data(), that.data(), size())`
  567. * \post `at(size()) == Char(0)`
  568. */
  569. constexpr BasicFixedString(const BasicFixedString& /*that*/) = default;
  570. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  571. * Construct from a differently-sized BasicFixedString
  572. * \pre `that.size() <= N`
  573. * \post `size() == that.size()`
  574. * \post `0 == strncmp(data(), that.data(), size())`
  575. * \post `at(size()) == Char(0)`
  576. * \throw std::out_of_range when that.size() > N. When M <= N, this
  577. * constructor will never throw.
  578. * \note Conversions from larger-capacity BasicFixedString objects to smaller
  579. * ones (`M > N`) are allowed as long as the *size()* of the source string
  580. * is small enough.
  581. */
  582. template <std::size_t M>
  583. constexpr /* implicit */ BasicFixedString(
  584. const BasicFixedString<Char, M>& that) noexcept(M <= N)
  585. : BasicFixedString{that, 0u, that.size_} {}
  586. // Why is this deleted? To avoid confusion with the constructor that takes
  587. // a const Char* and a count.
  588. template <std::size_t M>
  589. constexpr BasicFixedString(
  590. const BasicFixedString<Char, M>& that,
  591. std::size_t pos) noexcept(false) = delete;
  592. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  593. * Construct from an BasicFixedString, an offset, and a count
  594. * \param that The source string
  595. * \param pos The starting position in `that`
  596. * \param count The number of characters to copy. If `npos`, `count` is taken
  597. * to be `that.size()-pos`.
  598. * \pre `pos <= that.size()`
  599. * \pre `count <= that.size()-pos && count <= N`
  600. * \post `size() == count`
  601. * \post `0 == strncmp(data(), that.data()+pos, size())`
  602. * \post `at(size()) == Char(0)`
  603. * \throw std::out_of_range when pos+count > that.size(), or when
  604. * `count > N`
  605. */
  606. template <std::size_t M>
  607. constexpr BasicFixedString(
  608. const BasicFixedString<Char, M>& that,
  609. std::size_t pos,
  610. std::size_t count) noexcept(false)
  611. : BasicFixedString{
  612. that.data_,
  613. that.size_,
  614. folly::make_index_sequence<(M < N ? M : N)>{},
  615. pos,
  616. detail::fixedstring::checkOverflow(
  617. detail::fixedstring::checkOverflowOrNpos(
  618. count,
  619. that.size_ -
  620. detail::fixedstring::checkOverflow(pos, that.size_)),
  621. N)} {}
  622. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  623. * Construct from a string literal
  624. * \pre `M-1 <= N`
  625. * \pre `that[M-1] == Char(0)`
  626. * \post `0 == strncmp(data(), that, M-1)`
  627. * \post `size() == M-1`
  628. * \post `at(size()) == Char(0)`
  629. */
  630. template <std::size_t M, class = typename std::enable_if<(M - 1u <= N)>::type>
  631. constexpr /* implicit */ BasicFixedString(const Char (&that)[M]) noexcept
  632. : BasicFixedString{detail::fixedstring::checkNullTerminated(that),
  633. M - 1u,
  634. folly::make_index_sequence<M - 1u>{}} {}
  635. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  636. * Construct from a `const Char*` and count
  637. * \pre `that` points to an array of at least `count` characters.
  638. * \pre `count <= N`
  639. * \post `size() == count`
  640. * \post `0 == strncmp(data(), that, size())`
  641. * \post `at(size()) == Char(0)`
  642. * \throw std::out_of_range when count > N
  643. */
  644. constexpr BasicFixedString(const Char* that, std::size_t count) noexcept(
  645. false)
  646. : BasicFixedString{that,
  647. detail::fixedstring::checkOverflow(count, N),
  648. Indices{}} {}
  649. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  650. * Construct an BasicFixedString that contains `count` characters, all
  651. * of which are `ch`.
  652. * \pre `count <= N`
  653. * \post `size() == count`
  654. * \post `npos == find_first_not_of(ch)`
  655. * \post `at(size()) == Char(0)`
  656. * \throw std::out_of_range when count > N
  657. */
  658. constexpr BasicFixedString(std::size_t count, Char ch) noexcept(false)
  659. : BasicFixedString{detail::fixedstring::checkOverflow(count, N),
  660. ch,
  661. Indices{}} {}
  662. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  663. * Construct an BasicFixedString from a `std::initializer_list` of
  664. * characters.
  665. * \pre `il.size() <= N`
  666. * \post `size() == count`
  667. * \post `0 == strncmp(data(), il.begin(), size())`
  668. * \post `at(size()) == Char(0)`
  669. * \throw std::out_of_range when il.size() > N
  670. */
  671. constexpr BasicFixedString(std::initializer_list<Char> il) noexcept(false)
  672. : BasicFixedString{il.begin(), il.size()} {}
  673. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=(
  674. const BasicFixedString&) noexcept = default;
  675. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  676. * Assign from a `BasicFixedString<Char, M>`.
  677. * \pre `that.size() <= N`
  678. * \post `size() == that.size()`
  679. * \post `0 == strncmp(data(), that.begin(), size())`
  680. * \post `at(size()) == Char(0)`
  681. * \throw std::out_of_range when that.size() > N. When M <= N, this
  682. * assignment operator will never throw.
  683. * \note Assignments from larger-capacity BasicFixedString objects to smaller
  684. * ones (`M > N`) are allowed as long as the *size* of the source string is
  685. * small enough.
  686. * \return `*this`
  687. */
  688. template <std::size_t M>
  689. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=(
  690. const BasicFixedString<Char, M>& that) noexcept(M <= N) {
  691. detail::fixedstring::checkOverflow(that.size_, N);
  692. size_ = that.copy(data_, that.size_);
  693. data_[size_] = Char(0);
  694. return *this;
  695. }
  696. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  697. * Assign from a null-terminated array of characters.
  698. * \pre `M < N`
  699. * \pre `that` has no embedded null characters
  700. * \pre `that[M-1]==Char(0)`
  701. * \post `size() == M-1`
  702. * \post `0 == strncmp(data(), that, size())`
  703. * \post `at(size()) == Char(0)`
  704. * \return `*this`
  705. */
  706. template <std::size_t M, class = typename std::enable_if<(M - 1u <= N)>::type>
  707. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=(
  708. const Char (&that)[M]) noexcept {
  709. return assign(detail::fixedstring::checkNullTerminated(that), M - 1u);
  710. }
  711. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  712. * Assign from an `initializer_list` of characters.
  713. * \pre `il.size() <= N`
  714. * \post `size() == il.size()`
  715. * \post `0 == strncmp(data(), il.begin(), size())`
  716. * \post `at(size()) == Char(0)`
  717. * \throw std::out_of_range when il.size() > N
  718. * \return `*this`
  719. */
  720. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=(
  721. std::initializer_list<Char> il) noexcept(false) {
  722. detail::fixedstring::checkOverflow(il.size(), N);
  723. for (std::size_t i = 0u; i < il.size(); ++i) {
  724. data_[i] = il.begin()[i];
  725. }
  726. size_ = il.size();
  727. data_[size_] = Char(0);
  728. return *this;
  729. }
  730. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  731. * Conversion to folly::Range
  732. * \return `Range<Char*>{begin(), end()}`
  733. */
  734. FOLLY_CPP14_CONSTEXPR Range<Char*> toRange() noexcept {
  735. return {begin(), end()};
  736. }
  737. /**
  738. * \overload
  739. */
  740. constexpr Range<const Char*> toRange() const noexcept {
  741. return {begin(), end()};
  742. }
  743. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  744. * Conversion to std::basic_string<Char>
  745. * \return `std::basic_string<Char>{begin(), end()}`
  746. */
  747. /* implicit */ operator std::basic_string<Char>() const noexcept(false) {
  748. return std::basic_string<Char>{begin(), end()};
  749. }
  750. std::basic_string<Char> toStdString() const noexcept(false) {
  751. return std::basic_string<Char>{begin(), end()};
  752. }
  753. // Think hard about whether this is a good idea. It's certainly better than
  754. // an implicit conversion to `const Char*` since `delete "hi"_fs` will fail
  755. // to compile. But it creates ambiguities when passing a FixedString to an
  756. // API that has overloads for `const char*` and `folly::Range`, for instance.
  757. // using ArrayType = Char[N];
  758. // FOLLY_CPP14_CONSTEXPR /* implicit */ operator ArrayType&() noexcept {
  759. // return data_;
  760. // }
  761. // using ConstArrayType = const Char[N];
  762. // constexpr /* implicit */ operator ConstArrayType&() const noexcept {
  763. // return data_;
  764. // }
  765. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  766. * Assigns a sequence of `count` characters of value `ch`.
  767. * \param count The count of characters.
  768. * \param ch
  769. * \pre `count <= N`
  770. * \post `size() == count`
  771. * \post `npos == find_first_not_of(ch)`
  772. * \post `at(size()) == Char(0)`
  773. * \throw std::out_of_range when count > N
  774. * \return `*this`
  775. */
  776. FOLLY_CPP14_CONSTEXPR BasicFixedString& assign(
  777. std::size_t count,
  778. Char ch) noexcept(false) {
  779. detail::fixedstring::checkOverflow(count, N);
  780. for (std::size_t i = 0u; i < count; ++i) {
  781. data_[i] = ch;
  782. }
  783. size_ = count;
  784. data_[size_] = Char(0);
  785. return *this;
  786. }
  787. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  788. * Assigns characters from an `BasicFixedString` to this object.
  789. * \note Equivalent to `assign(that, 0, that.size())`
  790. */
  791. template <std::size_t M>
  792. FOLLY_CPP14_CONSTEXPR BasicFixedString& assign(
  793. const BasicFixedString<Char, M>& that) noexcept(M <= N) {
  794. return *this = that;
  795. }
  796. // Why is this overload deleted? So users aren't confused by the difference
  797. // between str.assign("foo", N) and str.assign("foo"_fs, N). In the former,
  798. // N is a count of characters. In the latter, it would be a position, which
  799. // totally changes the meaning of the code.
  800. template <std::size_t M>
  801. FOLLY_CPP14_CONSTEXPR BasicFixedString& assign(
  802. const BasicFixedString<Char, M>& that,
  803. std::size_t pos) noexcept(false) = delete;
  804. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  805. * Assigns `count` characters from an `BasicFixedString` to this object,
  806. * starting at position `pos` in the source object.
  807. * \param that The source string.
  808. * \param pos The starting position in the source string.
  809. * \param count The number of characters to copy. If `npos`, `count` is taken
  810. * to be `that.size()-pos`.
  811. * \pre `pos <= that.size()`
  812. * \pre `count <= that.size()-pos`
  813. * \pre `count <= N`
  814. * \post `size() == count`
  815. * \post `0 == strncmp(data(), that.begin() + pos, count)`
  816. * \post `at(size()) == Char(0)`
  817. * \throw std::out_of_range when pos > that.size() or count > that.size()-pos
  818. * or count > N.
  819. * \return `*this`
  820. */
  821. template <std::size_t M>
  822. FOLLY_CPP14_CONSTEXPR BasicFixedString& assign(
  823. const BasicFixedString<Char, M>& that,
  824. std::size_t pos,
  825. std::size_t count) noexcept(false) {
  826. detail::fixedstring::checkOverflow(pos, that.size_);
  827. return assign(
  828. that.data_ + pos,
  829. detail::fixedstring::checkOverflowOrNpos(count, that.size_ - pos));
  830. }
  831. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  832. * Assigns characters from an `BasicFixedString` to this object.
  833. * \pre `that` contains no embedded nulls.
  834. * \pre `that[M-1] == Char(0)`
  835. * \note Equivalent to `assign(that, M - 1)`
  836. */
  837. template <std::size_t M, class = typename std::enable_if<(M - 1u <= N)>::type>
  838. FOLLY_CPP14_CONSTEXPR BasicFixedString& assign(
  839. const Char (&that)[M]) noexcept {
  840. return assign(detail::fixedstring::checkNullTerminated(that), M - 1u);
  841. }
  842. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  843. * Assigns `count` characters from a range of characters to this object.
  844. * \param that A pointer to a range of characters.
  845. * \param count The number of characters to copy.
  846. * \pre `that` points to at least `count` characters.
  847. * \pre `count <= N`
  848. * \post `size() == count`
  849. * \post `0 == strncmp(data(), that, count)`
  850. * \post `at(size()) == Char(0)`
  851. * \throw std::out_of_range when count > N
  852. * \return `*this`
  853. */
  854. FOLLY_CPP14_CONSTEXPR BasicFixedString& assign(
  855. const Char* that,
  856. std::size_t count) noexcept(false) {
  857. detail::fixedstring::checkOverflow(count, N);
  858. for (std::size_t i = 0u; i < count; ++i) {
  859. data_[i] = that[i];
  860. }
  861. size_ = count;
  862. data_[size_] = Char(0);
  863. return *this;
  864. }
  865. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  866. * Swap the contents of this string with `that`.
  867. */
  868. FOLLY_CPP14_CONSTEXPR void swap(BasicFixedString& that) noexcept {
  869. // less-than-or-equal here to copy the null terminator:
  870. for (std::size_t i = 0u; i <= folly::constexpr_max(size_, that.size_);
  871. ++i) {
  872. detail::fixedstring::constexpr_swap(data_[i], that.data_[i]);
  873. }
  874. detail::fixedstring::constexpr_swap(size_, that.size_);
  875. }
  876. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  877. * Return a pointer to a range of `size()+1` characters, the last of which
  878. * is `Char(0)`.
  879. */
  880. FOLLY_CPP14_CONSTEXPR Char* data() noexcept {
  881. return data_;
  882. }
  883. /**
  884. * \overload
  885. */
  886. constexpr const Char* data() const noexcept {
  887. return data_;
  888. }
  889. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  890. * \return `data()`.
  891. */
  892. constexpr const Char* c_str() const noexcept {
  893. return data_;
  894. }
  895. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  896. * \return `data()`.
  897. */
  898. FOLLY_CPP14_CONSTEXPR Char* begin() noexcept {
  899. return data_;
  900. }
  901. /**
  902. * \overload
  903. */
  904. constexpr const Char* begin() const noexcept {
  905. return data_;
  906. }
  907. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  908. * \return `data()`.
  909. */
  910. constexpr const Char* cbegin() const noexcept {
  911. return begin();
  912. }
  913. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  914. * \return `data() + size()`.
  915. */
  916. FOLLY_CPP14_CONSTEXPR Char* end() noexcept {
  917. return data_ + size_;
  918. }
  919. /**
  920. * \overload
  921. */
  922. constexpr const Char* end() const noexcept {
  923. return data_ + size_;
  924. }
  925. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  926. * \return `data() + size()`.
  927. */
  928. constexpr const Char* cend() const noexcept {
  929. return end();
  930. }
  931. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  932. * Returns a reverse iterator to the first character of the reversed string.
  933. * It corresponds to the last + 1 character of the non-reversed string.
  934. */
  935. FOLLY_CPP14_CONSTEXPR reverse_iterator rbegin() noexcept {
  936. return reverse_iterator{data_ + size_};
  937. }
  938. /**
  939. * \overload
  940. */
  941. constexpr const_reverse_iterator rbegin() const noexcept {
  942. return const_reverse_iterator{data_ + size_};
  943. }
  944. /**
  945. * \note Equivalent to `rbegin()` on a const-qualified reference to `*this`.
  946. */
  947. constexpr const_reverse_iterator crbegin() const noexcept {
  948. return rbegin();
  949. }
  950. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  951. * Returns a reverse iterator to the last + 1 character of the reversed
  952. * string. It corresponds to the first character of the non-reversed string.
  953. */
  954. FOLLY_CPP14_CONSTEXPR reverse_iterator rend() noexcept {
  955. return reverse_iterator{data_};
  956. }
  957. /**
  958. * \overload
  959. */
  960. constexpr const_reverse_iterator rend() const noexcept {
  961. return const_reverse_iterator{data_};
  962. }
  963. /**
  964. * \note Equivalent to `rend()` on a const-qualified reference to `*this`.
  965. */
  966. constexpr const_reverse_iterator crend() const noexcept {
  967. return rend();
  968. }
  969. /**
  970. * \return The number of `Char` elements in the string.
  971. */
  972. constexpr std::size_t size() const noexcept {
  973. return size_;
  974. }
  975. /**
  976. * \return The number of `Char` elements in the string.
  977. */
  978. constexpr std::size_t length() const noexcept {
  979. return size_;
  980. }
  981. /**
  982. * \return True if and only if `size() == 0`.
  983. */
  984. constexpr bool empty() const noexcept {
  985. return 0u == size_;
  986. }
  987. /**
  988. * \return `N`.
  989. */
  990. static constexpr std::size_t capacity() noexcept {
  991. return N;
  992. }
  993. /**
  994. * \return `N`.
  995. */
  996. static constexpr std::size_t max_size() noexcept {
  997. return N;
  998. }
  999. // We would need to reimplement folly::Hash to make this
  1000. // constexpr. :-(
  1001. std::uint32_t hash() const noexcept {
  1002. return folly::hsieh_hash32_buf(data_, size_);
  1003. }
  1004. /**
  1005. * \note `at(size())` is allowed will return `Char(0)`.
  1006. * \return `*(data() + i)`
  1007. * \throw std::out_of_range when i > size()
  1008. */
  1009. FOLLY_CPP14_CONSTEXPR Char& at(std::size_t i) noexcept(false) {
  1010. return i <= size_ ? data_[i]
  1011. : (throw_exception<std::out_of_range>(
  1012. "Out of range in BasicFixedString::at"),
  1013. data_[size_]);
  1014. }
  1015. /**
  1016. * \overload
  1017. */
  1018. constexpr const Char& at(std::size_t i) const noexcept(false) {
  1019. return i <= size_ ? data_[i]
  1020. : (throw_exception<std::out_of_range>(
  1021. "Out of range in BasicFixedString::at"),
  1022. data_[size_]);
  1023. }
  1024. /**
  1025. * \pre `i <= size()`
  1026. * \note `(*this)[size()]` is allowed will return `Char(0)`.
  1027. * \return `*(data() + i)`
  1028. */
  1029. FOLLY_CPP14_CONSTEXPR Char& operator[](std::size_t i) noexcept {
  1030. #ifdef NDEBUG
  1031. return data_[i];
  1032. #else
  1033. return data_[detail::fixedstring::checkOverflow(i, size_)];
  1034. #endif
  1035. }
  1036. /**
  1037. * \overload
  1038. */
  1039. constexpr const Char& operator[](std::size_t i) const noexcept {
  1040. #ifdef NDEBUG
  1041. return data_[i];
  1042. #else
  1043. return data_[detail::fixedstring::checkOverflow(i, size_)];
  1044. #endif
  1045. }
  1046. /**
  1047. * \note Equivalent to `(*this)[0]`
  1048. */
  1049. FOLLY_CPP14_CONSTEXPR Char& front() noexcept {
  1050. return (*this)[0u];
  1051. }
  1052. /**
  1053. * \overload
  1054. */
  1055. constexpr const Char& front() const noexcept {
  1056. return (*this)[0u];
  1057. }
  1058. /**
  1059. * \note Equivalent to `at(size()-1)`
  1060. * \pre `!empty()`
  1061. */
  1062. FOLLY_CPP14_CONSTEXPR Char& back() noexcept {
  1063. #ifdef NDEBUG
  1064. return data_[size_ - 1u];
  1065. #else
  1066. return data_[size_ - detail::fixedstring::checkOverflow(1u, size_)];
  1067. #endif
  1068. }
  1069. /**
  1070. * \overload
  1071. */
  1072. constexpr const Char& back() const noexcept {
  1073. #ifdef NDEBUG
  1074. return data_[size_ - 1u];
  1075. #else
  1076. return data_[size_ - detail::fixedstring::checkOverflow(1u, size_)];
  1077. #endif
  1078. }
  1079. /**
  1080. * Clears the contents of this string.
  1081. * \post `size() == 0u`
  1082. * \post `at(size()) == Char(0)`
  1083. */
  1084. FOLLY_CPP14_CONSTEXPR void clear() noexcept {
  1085. data_[0u] = Char(0);
  1086. size_ = 0u;
  1087. }
  1088. /**
  1089. * \note Equivalent to `append(1u, ch)`.
  1090. */
  1091. FOLLY_CPP14_CONSTEXPR void push_back(Char ch) noexcept(false) {
  1092. detail::fixedstring::checkOverflow(1u, N - size_);
  1093. data_[size_] = ch;
  1094. data_[++size_] = Char(0);
  1095. }
  1096. /**
  1097. * \note Equivalent to `cappend(1u, ch)`.
  1098. */
  1099. constexpr BasicFixedString<Char, N + 1u> cpush_back(Char ch) const noexcept {
  1100. return cappend(ch);
  1101. }
  1102. /**
  1103. * Removes the last character from the string.
  1104. * \pre `!empty()`
  1105. * \post `size()` is one fewer than before calling `pop_back()`.
  1106. * \post `at(size()) == Char(0)`
  1107. * \post The characters in the half-open range `[0,size()-1)` are unmodified.
  1108. * \throw std::out_of_range if empty().
  1109. */
  1110. FOLLY_CPP14_CONSTEXPR void pop_back() noexcept(false) {
  1111. detail::fixedstring::checkOverflow(1u, size_);
  1112. --size_;
  1113. data_[size_] = Char(0);
  1114. }
  1115. /**
  1116. * Returns a new string with the first `size()-1` characters from this string.
  1117. * \pre `!empty()`
  1118. * \note Equivalent to `BasicFixedString<Char, N-1u>{*this, 0u, size()-1u}`
  1119. * \throw std::out_of_range if empty().
  1120. */
  1121. constexpr BasicFixedString<Char, N - 1u> cpop_back() const noexcept(false) {
  1122. return {*this, 0u, size_ - detail::fixedstring::checkOverflow(1u, size_)};
  1123. }
  1124. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1125. * Appends `count` copies of `ch` to this string.
  1126. * \pre `count + old_size <= N`
  1127. * \post The first `old_size` characters of the string are unmodified.
  1128. * \post `size() == old_size + count`
  1129. * \throw std::out_of_range if count > N - size().
  1130. */
  1131. FOLLY_CPP14_CONSTEXPR BasicFixedString& append(
  1132. std::size_t count,
  1133. Char ch) noexcept(false) {
  1134. detail::fixedstring::checkOverflow(count, N - size_);
  1135. for (std::size_t i = 0u; i < count; ++i) {
  1136. data_[size_ + i] = ch;
  1137. }
  1138. size_ += count;
  1139. data_[size_] = Char(0);
  1140. return *this;
  1141. }
  1142. /**
  1143. * \note Equivalent to `append(*this, 0, that.size())`.
  1144. */
  1145. template <std::size_t M>
  1146. FOLLY_CPP14_CONSTEXPR BasicFixedString& append(
  1147. const BasicFixedString<Char, M>& that) noexcept(false) {
  1148. return append(that, 0u, that.size_);
  1149. }
  1150. // Why is this overload deleted? So as not to get confused with
  1151. // append("null-terminated", N), where N would be a count instead
  1152. // of a position.
  1153. template <std::size_t M>
  1154. FOLLY_CPP14_CONSTEXPR BasicFixedString& append(
  1155. const BasicFixedString<Char, M>& that,
  1156. std::size_t pos) noexcept(false) = delete;
  1157. /**
  1158. * Appends `count` characters from another string to this one, starting at a
  1159. * given offset, `pos`.
  1160. * \param that The source string.
  1161. * \param pos The starting position in the source string.
  1162. * \param count The number of characters to append. If `npos`, `count` is
  1163. * taken to be `that.size()-pos`.
  1164. * \pre `pos <= that.size()`
  1165. * \pre `count <= that.size() - pos`
  1166. * \pre `old_size + count <= N`
  1167. * \post The first `old_size` characters of the string are unmodified.
  1168. * \post `size() == old_size + count`
  1169. * \post `at(size()) == Char(0)`
  1170. * \throw std::out_of_range if pos + count > that.size() or if
  1171. * `old_size + count > N`.
  1172. */
  1173. template <std::size_t M>
  1174. FOLLY_CPP14_CONSTEXPR BasicFixedString& append(
  1175. const BasicFixedString<Char, M>& that,
  1176. std::size_t pos,
  1177. std::size_t count) noexcept(false) {
  1178. detail::fixedstring::checkOverflow(pos, that.size_);
  1179. count = detail::fixedstring::checkOverflowOrNpos(count, that.size_ - pos);
  1180. detail::fixedstring::checkOverflow(count, N - size_);
  1181. for (std::size_t i = 0u; i < count; ++i) {
  1182. data_[size_ + i] = that.data_[pos + i];
  1183. }
  1184. size_ += count;
  1185. data_[size_] = Char(0);
  1186. return *this;
  1187. }
  1188. /**
  1189. * \note Equivalent to `append(that, strlen(that))`.
  1190. */
  1191. FOLLY_CPP14_CONSTEXPR BasicFixedString& append(const Char* that) noexcept(
  1192. false) {
  1193. return append(that, folly::constexpr_strlen(that));
  1194. }
  1195. /**
  1196. * Appends `count` characters from the specified character array.
  1197. * \pre `that` points to a range of at least `count` characters.
  1198. * \pre `count + old_size <= N`
  1199. * \post The first `old_size` characters of the string are unmodified.
  1200. * \post `size() == old_size + count`
  1201. * \post `at(size()) == Char(0)`
  1202. * \throw std::out_of_range if old_size + count > N.
  1203. */
  1204. FOLLY_CPP14_CONSTEXPR BasicFixedString& append(
  1205. const Char* that,
  1206. std::size_t count) noexcept(false) {
  1207. detail::fixedstring::checkOverflow(count, N - size_);
  1208. for (std::size_t i = 0u; i < count; ++i) {
  1209. data_[size_ + i] = that[i];
  1210. }
  1211. size_ += count;
  1212. data_[size_] = Char(0);
  1213. return *this;
  1214. }
  1215. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1216. * Creates a new string by appending a character to an existing string, which
  1217. * is left unmodified.
  1218. * \note Equivalent to `*this + ch`
  1219. */
  1220. constexpr BasicFixedString<Char, N + 1u> cappend(Char ch) const noexcept {
  1221. return *this + ch;
  1222. }
  1223. /**
  1224. * Creates a new string by appending a string to an existing string, which
  1225. * is left unmodified.
  1226. * \note Equivalent to `*this + ch`
  1227. */
  1228. template <std::size_t M>
  1229. constexpr BasicFixedString<Char, N + M> cappend(
  1230. const BasicFixedString<Char, M>& that) const noexcept {
  1231. return *this + that;
  1232. }
  1233. // Deleted to avoid confusion with append("char*", N), where N is a count
  1234. // instead of a position.
  1235. template <std::size_t M>
  1236. constexpr BasicFixedString<Char, N + M> cappend(
  1237. const BasicFixedString<Char, M>& that,
  1238. std::size_t pos) const noexcept(false) = delete;
  1239. /**
  1240. * Creates a new string by appending characters from one string to another,
  1241. * which is left unmodified.
  1242. * \note Equivalent to `*this + that.substr(pos, count)`
  1243. */
  1244. template <std::size_t M>
  1245. constexpr BasicFixedString<Char, N + M> cappend(
  1246. const BasicFixedString<Char, M>& that,
  1247. std::size_t pos,
  1248. std::size_t count) const noexcept(false) {
  1249. return creplace(size_, 0u, that, pos, count);
  1250. }
  1251. /**
  1252. * Creates a new string by appending a string literal to a string,
  1253. * which is left unmodified.
  1254. * \note Equivalent to `*this + that`
  1255. */
  1256. template <std::size_t M>
  1257. constexpr BasicFixedString<Char, N + M - 1u> cappend(
  1258. const Char (&that)[M]) const noexcept {
  1259. return creplace(size_, 0u, that);
  1260. }
  1261. // Deleted to avoid confusion with append("char*", N), where N is a count
  1262. // instead of a position
  1263. template <std::size_t M>
  1264. constexpr BasicFixedString<Char, N + M - 1u> cappend(
  1265. const Char (&that)[M],
  1266. std::size_t pos) const noexcept(false) = delete;
  1267. /**
  1268. * Creates a new string by appending characters from one string to another,
  1269. * which is left unmodified.
  1270. * \note Equivalent to `*this + makeFixedString(that).substr(pos, count)`
  1271. */
  1272. template <std::size_t M>
  1273. constexpr BasicFixedString<Char, N + M - 1u>
  1274. cappend(const Char (&that)[M], std::size_t pos, std::size_t count) const
  1275. noexcept(false) {
  1276. return creplace(size_, 0u, that, pos, count);
  1277. }
  1278. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1279. * Appends characters from a null-terminated string literal to this string.
  1280. * \note Equivalent to `append(that)`.
  1281. */
  1282. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=(const Char* that) noexcept(
  1283. false) {
  1284. return append(that);
  1285. }
  1286. /**
  1287. * Appends characters from another string to this one.
  1288. * \note Equivalent to `append(that)`.
  1289. */
  1290. template <std::size_t M>
  1291. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=(
  1292. const BasicFixedString<Char, M>& that) noexcept(false) {
  1293. return append(that, 0u, that.size_);
  1294. }
  1295. /**
  1296. * Appends a character to this string.
  1297. * \note Equivalent to `push_back(ch)`.
  1298. */
  1299. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=(Char ch) noexcept(false) {
  1300. push_back(ch);
  1301. return *this;
  1302. }
  1303. /**
  1304. * Appends characters from an `initializer_list` to this string.
  1305. * \note Equivalent to `append(il.begin(), il.size())`.
  1306. */
  1307. FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=(
  1308. std::initializer_list<Char> il) noexcept(false) {
  1309. return append(il.begin(), il.size());
  1310. }
  1311. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1312. * Erase all characters from this string.
  1313. * \note Equivalent to `clear()`
  1314. * \return *this;
  1315. */
  1316. FOLLY_CPP14_CONSTEXPR BasicFixedString& erase() noexcept {
  1317. clear();
  1318. return *this;
  1319. }
  1320. /**
  1321. * Erases `count` characters from position `pos`. If `count` is `npos`,
  1322. * erases from `pos` to the end of the string.
  1323. * \pre `pos <= size()`
  1324. * \pre `count <= size() - pos || count == npos`
  1325. * \post `size() == old_size - min(count, old_size - pos)`
  1326. * \post `at(size()) == Char(0)`
  1327. * \return *this;
  1328. * \throw std::out_of_range when pos > size().
  1329. */
  1330. FOLLY_CPP14_CONSTEXPR BasicFixedString& erase(
  1331. std::size_t pos,
  1332. std::size_t count = npos) noexcept(false) {
  1333. using A = const Char[1];
  1334. return replace(
  1335. pos,
  1336. detail::fixedstring::checkOverflowOrNpos(
  1337. count, size_ - detail::fixedstring::checkOverflow(pos, size_)),
  1338. A{Char(0)},
  1339. 0u);
  1340. }
  1341. /**
  1342. * \note Equivalent to `erase(first - data(), 1)`
  1343. * \return A pointer to the first character after the erased character.
  1344. */
  1345. FOLLY_CPP14_CONSTEXPR Char* erase(const Char* first) noexcept(false) {
  1346. erase(first - data_, 1u);
  1347. return data_ + (first - data_);
  1348. }
  1349. /**
  1350. * \note Equivalent to `erase(first - data(), last - first)`
  1351. * \return A pointer to the first character after the erased characters.
  1352. */
  1353. FOLLY_CPP14_CONSTEXPR Char* erase(
  1354. const Char* first,
  1355. const Char* last) noexcept(false) {
  1356. erase(first - data_, last - first);
  1357. return data_ + (first - data_);
  1358. }
  1359. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1360. * Create a new string by erasing all the characters from this string.
  1361. * \note Equivalent to `BasicFixedString<Char, 0>{}`
  1362. */
  1363. constexpr BasicFixedString<Char, 0u> cerase() const noexcept {
  1364. return {};
  1365. }
  1366. /**
  1367. * Create a new string by erasing all the characters after position `pos` from
  1368. * this string.
  1369. * \note Equivalent to `creplace(pos, min(count, pos - size()), "")`
  1370. */
  1371. constexpr BasicFixedString cerase(std::size_t pos, std::size_t count = npos)
  1372. const noexcept(false) {
  1373. using A = const Char[1];
  1374. return creplace(
  1375. pos,
  1376. detail::fixedstring::checkOverflowOrNpos(
  1377. count, size_ - detail::fixedstring::checkOverflow(pos, size_)),
  1378. A{Char(0)});
  1379. }
  1380. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1381. * Compare two strings for lexicographical ordering.
  1382. * \note Equivalent to
  1383. * `compare(0, size(), that.data(), that.size())`
  1384. */
  1385. template <std::size_t M>
  1386. constexpr int compare(const BasicFixedString<Char, M>& that) const noexcept {
  1387. return compare(0u, size_, that, 0u, that.size_);
  1388. }
  1389. /**
  1390. * Compare two strings for lexicographical ordering.
  1391. * \note Equivalent to
  1392. * `compare(this_pos, this_count, that.data(), that.size())`
  1393. */
  1394. template <std::size_t M>
  1395. constexpr int compare(
  1396. std::size_t this_pos,
  1397. std::size_t this_count,
  1398. const BasicFixedString<Char, M>& that) const noexcept(false) {
  1399. return compare(this_pos, this_count, that, 0u, that.size_);
  1400. }
  1401. /**
  1402. * Compare two strings for lexicographical ordering.
  1403. * \note Equivalent to
  1404. * `compare(this_pos, this_count, that.data() + that_pos, that_count)`
  1405. */
  1406. template <std::size_t M>
  1407. constexpr int compare(
  1408. std::size_t this_pos,
  1409. std::size_t this_count,
  1410. const BasicFixedString<Char, M>& that,
  1411. std::size_t that_pos,
  1412. std::size_t that_count) const noexcept(false) {
  1413. return static_cast<int>(detail::fixedstring::compare_(
  1414. data_,
  1415. detail::fixedstring::checkOverflow(this_pos, size_),
  1416. detail::fixedstring::checkOverflow(this_count, size_ - this_pos) +
  1417. this_pos,
  1418. that.data_,
  1419. detail::fixedstring::checkOverflow(that_pos, that.size_),
  1420. detail::fixedstring::checkOverflow(that_count, that.size_ - that_pos) +
  1421. that_pos));
  1422. }
  1423. /**
  1424. * Compare two strings for lexicographical ordering.
  1425. * \note Equivalent to `compare(0, size(), that, strlen(that))`
  1426. */
  1427. constexpr int compare(const Char* that) const noexcept {
  1428. return compare(0u, size_, that, folly::constexpr_strlen(that));
  1429. }
  1430. /**
  1431. * \overload
  1432. */
  1433. constexpr int compare(Range<const Char*> that) const noexcept {
  1434. return compare(0u, size_, that.begin(), that.size());
  1435. }
  1436. /**
  1437. * Compare two strings for lexicographical ordering.
  1438. * \note Equivalent to
  1439. * `compare(this_pos, this_count, that, strlen(that))`
  1440. */
  1441. constexpr int compare(
  1442. std::size_t this_pos,
  1443. std::size_t this_count,
  1444. const Char* that) const noexcept(false) {
  1445. return compare(this_pos, this_count, that, folly::constexpr_strlen(that));
  1446. }
  1447. /**
  1448. * \overload
  1449. */
  1450. constexpr int compare(
  1451. std::size_t this_pos,
  1452. std::size_t this_count,
  1453. Range<const Char*> that) const noexcept(false) {
  1454. return compare(this_pos, this_count, that.begin(), that.size());
  1455. }
  1456. /**
  1457. * Compare two strings for lexicographical ordering.
  1458. *
  1459. * Let `A` be the the
  1460. * character sequence {`(*this)[this_pos]`, ...
  1461. * `(*this)[this_pos + this_count - 1]`}. Let `B` be the character sequence
  1462. * {`that[0]`, ...`that[count - 1]`}. Then...
  1463. *
  1464. * \return
  1465. * - `< 0` if `A` is ordered before the `B`
  1466. * - `> 0` if `B` is ordered before `A`
  1467. * - `0` if `A` equals `B`.
  1468. *
  1469. * \throw std::out_of_range if this_pos + this_count > size().
  1470. */
  1471. constexpr int compare(
  1472. std::size_t this_pos,
  1473. std::size_t this_count,
  1474. const Char* that,
  1475. std::size_t that_count) const noexcept(false) {
  1476. return static_cast<int>(detail::fixedstring::compare_(
  1477. data_,
  1478. detail::fixedstring::checkOverflow(this_pos, size_),
  1479. detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos) +
  1480. this_pos,
  1481. that,
  1482. 0u,
  1483. that_count));
  1484. }
  1485. constexpr int compare(
  1486. std::size_t this_pos,
  1487. std::size_t this_count,
  1488. Range<const Char*> that,
  1489. std::size_t that_count) const noexcept(false) {
  1490. return compare(
  1491. this_pos,
  1492. this_count,
  1493. that.begin(),
  1494. detail::fixedstring::checkOverflow(that_count, that.size()));
  1495. }
  1496. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1497. * Return a substring from `pos` to the end of the string.
  1498. * \note Equivalent to `BasicFixedString{*this, pos}`
  1499. */
  1500. constexpr BasicFixedString substr(std::size_t pos) const noexcept(false) {
  1501. return {*this, pos};
  1502. }
  1503. /**
  1504. * Return a substring from `pos` to the end of the string.
  1505. * \note Equivalent to `BasicFixedString{*this, pos, count}`
  1506. */
  1507. constexpr BasicFixedString substr(std::size_t pos, std::size_t count) const
  1508. noexcept(false) {
  1509. return {*this, pos, count};
  1510. }
  1511. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1512. * Replace the characters in the range denoted by the half-open range
  1513. * [`first`, `last`) with the string `that`.
  1514. * \pre `first` and `last` point to characters within this string (including
  1515. * the terminating null).
  1516. * \note Equivalent to
  1517. * `replace(first - data(), last - first, that.data(), that.size())`
  1518. */
  1519. template <std::size_t M>
  1520. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1521. const Char* first,
  1522. const Char* last,
  1523. const BasicFixedString<Char, M>& that) noexcept(false) {
  1524. return replace(first - data_, last - first, that, 0u, that.size_);
  1525. }
  1526. /**
  1527. * Replace `this_count` characters starting from position `this_pos` with the
  1528. * characters from string `that` starting at position `that_pos`.
  1529. * \pre `that_pos <= that.size()`
  1530. * \note Equivalent to
  1531. * <tt>replace(this_pos, this_count, that.data() + that_pos,
  1532. * that.size() - that_pos)</tt>
  1533. */
  1534. template <std::size_t M>
  1535. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1536. std::size_t this_pos,
  1537. std::size_t this_count,
  1538. const BasicFixedString<Char, M>& that,
  1539. std::size_t that_pos = 0u) noexcept(false) {
  1540. return replace(this_pos, this_count, that, that_pos, that.size_ - that_pos);
  1541. }
  1542. /**
  1543. * Replace `this_count` characters starting from position `this_pos` with
  1544. * `that_count` characters from string `that` starting at position
  1545. * `that_pos`.
  1546. * \pre `that_pos <= that.size() && that_count <= that.size() - that_pos`
  1547. * \note Equivalent to
  1548. * `replace(this_pos, this_count, that.data() + that_pos, that_count)`
  1549. */
  1550. template <std::size_t M>
  1551. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1552. std::size_t this_pos,
  1553. std::size_t this_count,
  1554. const BasicFixedString<Char, M>& that,
  1555. std::size_t that_pos,
  1556. std::size_t that_count) noexcept(false) {
  1557. return *this = creplace(this_pos, this_count, that, that_pos, that_count);
  1558. }
  1559. /**
  1560. * Replace `this_count` characters starting from position `this_pos` with
  1561. * the characters from the string literal `that`.
  1562. * \note Equivalent to
  1563. * `replace(this_pos, this_count, that, strlen(that))`
  1564. */
  1565. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1566. std::size_t this_pos,
  1567. std::size_t this_count,
  1568. const Char* that) noexcept(false) {
  1569. return replace(this_pos, this_count, that, folly::constexpr_strlen(that));
  1570. }
  1571. /**
  1572. * Replace the characters denoted by the half-open range [`first`,`last`) with
  1573. * the characters from the string literal `that`.
  1574. * \pre `first` and `last` point to characters within this string (including
  1575. * the terminating null).
  1576. * \note Equivalent to
  1577. * `replace(first - data(), last - first, that, strlen(that))`
  1578. */
  1579. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1580. const Char* first,
  1581. const Char* last,
  1582. const Char* that) noexcept(false) {
  1583. return replace(
  1584. first - data_, last - first, that, folly::constexpr_strlen(that));
  1585. }
  1586. /**
  1587. * Replace `this_count` characters starting from position `this_pos` with
  1588. * `that_count` characters from the character sequence pointed to by `that`.
  1589. * \param this_pos The starting offset within `*this` of the first character
  1590. * to be replaced.
  1591. * \param this_count The number of characters to be replaced. If `npos`,
  1592. * it is treated as if `this_count` were `size() - this_pos`.
  1593. * \param that A pointer to the replacement string.
  1594. * \param that_count The number of characters in the replacement string.
  1595. * \pre `this_pos <= size() && this_count <= size() - this_pos`
  1596. * \pre `that` points to a contiguous sequence of at least `that_count`
  1597. * characters
  1598. * \throw std::out_of_range on any of the following conditions:
  1599. * - `this_pos > size()`
  1600. * - `this_count > size() - this_pos`
  1601. * - `size() - this_count + that_count > N`
  1602. */
  1603. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1604. std::size_t this_pos,
  1605. std::size_t this_count,
  1606. const Char* that,
  1607. std::size_t that_count) noexcept(false) {
  1608. return *this = detail::fixedstring::Helper::replace_<Char>(
  1609. data_,
  1610. size_,
  1611. detail::fixedstring::checkOverflow(this_pos, size_),
  1612. detail::fixedstring::checkOverflowOrNpos(
  1613. this_count, size_ - this_pos),
  1614. that,
  1615. 0u,
  1616. that_count,
  1617. Indices{});
  1618. }
  1619. /**
  1620. * Replace `this_count` characters starting from position `this_pos` with
  1621. * `that_count` characters `ch`.
  1622. * \note Equivalent to
  1623. * `replace(this_pos, this_count, BasicFixedString{that_count, ch})`
  1624. */
  1625. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1626. std::size_t this_pos,
  1627. std::size_t this_count,
  1628. std::size_t that_count,
  1629. Char ch) noexcept(false) {
  1630. return replace(this_pos, this_count, BasicFixedString{that_count, ch});
  1631. }
  1632. /**
  1633. * Replace the characters denoted by the half-open range [`first`,`last`)
  1634. * with `that_count` characters `ch`.
  1635. * \note Equivalent to
  1636. * `replace(first - data(), last - first, BasicFixedString{that_count, ch})`
  1637. */
  1638. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1639. const Char* first,
  1640. const Char* last,
  1641. std::size_t that_count,
  1642. Char ch) noexcept(false) {
  1643. return replace(
  1644. first - data_, last - first, BasicFixedString{that_count, ch});
  1645. }
  1646. /**
  1647. * Replace the characters denoted by the half-open range [`first`,`last`) with
  1648. * the characters from the string literal `that`.
  1649. * \pre `first` and `last` point to characters within this string (including
  1650. * the terminating null).
  1651. * \note Equivalent to
  1652. * `replace(this_pos, this_count, il.begin(), il.size())`
  1653. */
  1654. FOLLY_CPP14_CONSTEXPR BasicFixedString& replace(
  1655. const Char* first,
  1656. const Char* last,
  1657. std::initializer_list<Char> il) noexcept(false) {
  1658. return replace(first - data_, last - first, il.begin(), il.size());
  1659. }
  1660. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1661. * Construct a new string by replacing `this_count` characters starting from
  1662. * position `this_pos` within this string with the characters from string
  1663. * `that` starting at position `that_pos`.
  1664. * \pre `that_pos <= that.size()`
  1665. * \note Equivalent to
  1666. * <tt>creplace(this_pos, this_count, that, that_pos,
  1667. * that.size() - that_pos)</tt>
  1668. */
  1669. template <std::size_t M>
  1670. constexpr BasicFixedString<Char, N + M> creplace(
  1671. std::size_t this_pos,
  1672. std::size_t this_count,
  1673. const BasicFixedString<Char, M>& that,
  1674. std::size_t that_pos = 0u) const noexcept(false) {
  1675. return creplace(
  1676. this_pos,
  1677. this_count,
  1678. that,
  1679. that_pos,
  1680. that.size_ - detail::fixedstring::checkOverflow(that_pos, that.size_));
  1681. }
  1682. /**
  1683. * Construct a new string by replacing `this_count` characters starting from
  1684. * position `this_pos` within this string with `that_count` characters from
  1685. * string `that` starting at position `that_pos`.
  1686. * \param this_pos The starting offset within `*this` of the first character
  1687. * to be replaced.
  1688. * \param this_count The number of characters to be replaced. If `npos`,
  1689. * it is treated as if `this_count` were `size() - this_pos`.
  1690. * \param that A string that contains the replacement string.
  1691. * \param that_pos The offset to the first character in the replacement
  1692. * string.
  1693. * \param that_count The number of characters in the replacement string.
  1694. * \pre `this_pos <= size() && this_count <= size() - this_pos`
  1695. * \pre `that_pos <= that.size() && that_count <= that.size() - that_pos`
  1696. * \post The size of the returned string is `size() - this_count + that_count`
  1697. * \note Equivalent to <tt>BasicFixedString<Char, N + M>{substr(0, this_pos) +
  1698. * that.substr(that_pos, that_count) + substr(this_pos + this_count)}</tt>
  1699. * \throw std::out_of_range on any of the following conditions:
  1700. * - `this_pos > size()`
  1701. * - `this_count > size() - this_pos`
  1702. * - `that_pos > that.size()`
  1703. * - `that_count > that.size() - that_pos`
  1704. */
  1705. template <std::size_t M>
  1706. constexpr BasicFixedString<Char, N + M> creplace(
  1707. std::size_t this_pos,
  1708. std::size_t this_count,
  1709. const BasicFixedString<Char, M>& that,
  1710. std::size_t that_pos,
  1711. std::size_t that_count) const noexcept(false) {
  1712. return detail::fixedstring::Helper::replace_<Char>(
  1713. data_,
  1714. size_,
  1715. detail::fixedstring::checkOverflow(this_pos, size_),
  1716. detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos),
  1717. that.data_,
  1718. detail::fixedstring::checkOverflow(that_pos, that.size_),
  1719. detail::fixedstring::checkOverflowOrNpos(
  1720. that_count, that.size_ - that_pos),
  1721. folly::make_index_sequence<N + M>{});
  1722. }
  1723. /**
  1724. * Construct a new string by replacing the characters denoted by the half-open
  1725. * range [`first`,`last`) within this string with the characters from string
  1726. * `that` starting at position `that_pos`.
  1727. * \pre `that_pos <= that.size()`
  1728. * \note Equivalent to
  1729. * <tt>creplace(first - data(), last - first, that, that_pos,
  1730. * that.size() - that_pos)</tt>
  1731. */
  1732. template <std::size_t M>
  1733. constexpr BasicFixedString<Char, N + M> creplace(
  1734. const Char* first,
  1735. const Char* last,
  1736. const BasicFixedString<Char, M>& that,
  1737. std::size_t that_pos = 0u) const noexcept(false) {
  1738. return creplace(
  1739. first - data_,
  1740. last - first,
  1741. that,
  1742. that_pos,
  1743. that.size_ - detail::fixedstring::checkOverflow(that_pos, that.size_));
  1744. }
  1745. /**
  1746. * Construct a new string by replacing the characters denoted by the half-open
  1747. * range [`first`,`last`) within this string with the `that_count`
  1748. * characters from string `that` starting at position `that_pos`.
  1749. * \note Equivalent to
  1750. * <tt>creplace(first - data(), last - first, that, that_pos,
  1751. * that_count)</tt>
  1752. */
  1753. template <std::size_t M>
  1754. constexpr BasicFixedString<Char, N + M> creplace(
  1755. const Char* first,
  1756. const Char* last,
  1757. const BasicFixedString<Char, M>& that,
  1758. std::size_t that_pos,
  1759. std::size_t that_count) const noexcept(false) {
  1760. return creplace(first - data_, last - first, that, that_pos, that_count);
  1761. }
  1762. /**
  1763. * Construct a new string by replacing `this_count` characters starting from
  1764. * position `this_pos` within this string with `M-1` characters from
  1765. * character array `that`.
  1766. * \pre `strlen(that) == M-1`
  1767. * \note Equivalent to
  1768. * <tt>creplace(this_pos, this_count, that, 0, M - 1)</tt>
  1769. */
  1770. template <std::size_t M>
  1771. constexpr BasicFixedString<Char, N + M - 1u> creplace(
  1772. std::size_t this_pos,
  1773. std::size_t this_count,
  1774. const Char (&that)[M]) const noexcept(false) {
  1775. return creplace(this_pos, this_count, that, 0u, M - 1u);
  1776. }
  1777. /**
  1778. * Replace `this_count` characters starting from position `this_pos` with
  1779. * `that_count` characters from the character array `that` starting at
  1780. * position `that_pos`.
  1781. * \param this_pos The starting offset within `*this` of the first character
  1782. * to be replaced.
  1783. * \param this_count The number of characters to be replaced. If `npos`,
  1784. * it is treated as if `this_count` were `size() - this_pos`.
  1785. * \param that An array of characters containing the replacement string.
  1786. * \param that_pos The starting offset of the replacement string.
  1787. * \param that_count The number of characters in the replacement string. If
  1788. * `npos`, it is treated as if `that_count` were `M - 1 - that_pos`
  1789. * \pre `this_pos <= size() && this_count <= size() - this_pos`
  1790. * \pre `that_pos <= M - 1 && that_count <= M - 1 - that_pos`
  1791. * \post The size of the returned string is `size() - this_count + that_count`
  1792. * \note Equivalent to <tt>BasicFixedString<Char, N + M - 1>{
  1793. * substr(0, this_pos) +
  1794. * makeFixedString(that).substr(that_pos, that_count) +
  1795. * substr(this_pos + this_count)}</tt>
  1796. * \throw std::out_of_range on any of the following conditions:
  1797. * - `this_pos > size()`
  1798. * - `this_count > size() - this_pos`
  1799. * - `that_pos >= M`
  1800. * - `that_count >= M - that_pos`
  1801. */
  1802. template <std::size_t M>
  1803. constexpr BasicFixedString<Char, N + M - 1u> creplace(
  1804. std::size_t this_pos,
  1805. std::size_t this_count,
  1806. const Char (&that)[M],
  1807. std::size_t that_pos,
  1808. std::size_t that_count) const noexcept(false) {
  1809. return detail::fixedstring::Helper::replace_<Char>(
  1810. data_,
  1811. size_,
  1812. detail::fixedstring::checkOverflow(this_pos, size_),
  1813. detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos),
  1814. detail::fixedstring::checkNullTerminated(that),
  1815. detail::fixedstring::checkOverflow(that_pos, M - 1u),
  1816. detail::fixedstring::checkOverflowOrNpos(that_count, M - 1u - that_pos),
  1817. folly::make_index_sequence<N + M - 1u>{});
  1818. }
  1819. /**
  1820. * Construct a new string by replacing the characters denoted by the half-open
  1821. * range [`first`,`last`) within this string with the first `M-1`
  1822. * characters from the character array `that`.
  1823. * \pre `strlen(that) == M-1`
  1824. * \note Equivalent to
  1825. * <tt>creplace(first - data(), last - first, that, 0, M-1)</tt>
  1826. */
  1827. template <std::size_t M>
  1828. constexpr BasicFixedString<Char, N + M - 1u>
  1829. creplace(const Char* first, const Char* last, const Char (&that)[M]) const
  1830. noexcept(false) {
  1831. return creplace(first - data_, last - first, that, 0u, M - 1u);
  1832. }
  1833. /**
  1834. * Construct a new string by replacing the characters denoted by the half-open
  1835. * range [`first`,`last`) within this string with the `that_count`
  1836. * characters from the character array `that` starting at position
  1837. * `that_pos`.
  1838. * \pre `strlen(that) == M-1`
  1839. * \note Equivalent to
  1840. * `creplace(first - data(), last - first, that, that_pos, that_count)`
  1841. */
  1842. template <std::size_t M>
  1843. constexpr BasicFixedString<Char, N + M - 1u> creplace(
  1844. const Char* first,
  1845. const Char* last,
  1846. const Char (&that)[M],
  1847. std::size_t that_pos,
  1848. std::size_t that_count) const noexcept(false) {
  1849. return creplace(first - data_, last - first, that, that_pos, that_count);
  1850. }
  1851. /**
  1852. * Copies `min(count, size())` characters starting from offset `0`
  1853. * from this string into the buffer pointed to by `dest`.
  1854. * \return The number of characters copied.
  1855. */
  1856. FOLLY_CPP14_CONSTEXPR std::size_t copy(Char* dest, std::size_t count) const
  1857. noexcept {
  1858. return copy(dest, count, 0u);
  1859. }
  1860. /**
  1861. * Copies `min(count, size() - pos)` characters starting from offset `pos`
  1862. * from this string into the buffer pointed to by `dest`.
  1863. * \pre `pos <= size()`
  1864. * \return The number of characters copied.
  1865. * \throw std::out_of_range if `pos > size()`
  1866. */
  1867. FOLLY_CPP14_CONSTEXPR std::size_t
  1868. copy(Char* dest, std::size_t count, std::size_t pos) const noexcept(false) {
  1869. detail::fixedstring::checkOverflow(pos, size_);
  1870. for (std::size_t i = 0u; i < count; ++i) {
  1871. if (i + pos == size_) {
  1872. return size_;
  1873. }
  1874. dest[i] = data_[i + pos];
  1875. }
  1876. return count;
  1877. }
  1878. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1879. * Resizes the current string.
  1880. * \note Equivalent to `resize(count, Char(0))`
  1881. */
  1882. FOLLY_CPP14_CONSTEXPR void resize(std::size_t count) noexcept(false) {
  1883. resize(count, Char(0));
  1884. }
  1885. /**
  1886. * Resizes the current string by setting the size to `count` and setting
  1887. * `data()[count]` to `Char(0)`. If `count > old_size`, the characters
  1888. * in the range [`old_size`,`count`) are set to `ch`.
  1889. */
  1890. FOLLY_CPP14_CONSTEXPR void resize(std::size_t count, Char ch) noexcept(
  1891. false) {
  1892. detail::fixedstring::checkOverflow(count, N);
  1893. if (count == size_) {
  1894. } else if (count < size_) {
  1895. size_ = count;
  1896. data_[size_] = Char(0);
  1897. } else {
  1898. for (; size_ < count; ++size_) {
  1899. data_[size_] = ch;
  1900. }
  1901. data_[size_] = Char(0);
  1902. }
  1903. }
  1904. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1905. * Finds the first occurrence of the character sequence `that` in this string.
  1906. * \note Equivalent to `find(that.data(), 0, that.size())`
  1907. */
  1908. template <std::size_t M>
  1909. constexpr std::size_t find(const BasicFixedString<Char, M>& that) const
  1910. noexcept {
  1911. return find(that, 0u);
  1912. }
  1913. /**
  1914. * Finds the first occurrence of the character sequence `that` in this string,
  1915. * starting at offset `pos`.
  1916. * \pre `pos <= size()`
  1917. * \note Equivalent to `find(that.data(), pos, that.size())`
  1918. */
  1919. template <std::size_t M>
  1920. constexpr std::size_t find(
  1921. const BasicFixedString<Char, M>& that,
  1922. std::size_t pos) const noexcept(false) {
  1923. return that.size_ <= size_ - detail::fixedstring::checkOverflow(pos, size_)
  1924. ? detail::fixedstring::find_(data_, size_, that.data_, pos, that.size_)
  1925. : npos;
  1926. }
  1927. /**
  1928. * Finds the first occurrence of the character sequence `that` in this string.
  1929. * \note Equivalent to `find(that.data(), 0, strlen(that))`
  1930. */
  1931. constexpr std::size_t find(const Char* that) const noexcept {
  1932. return find(that, 0u, folly::constexpr_strlen(that));
  1933. }
  1934. /**
  1935. * Finds the first occurrence of the character sequence `that` in this string,
  1936. * starting at offset `pos`.
  1937. * \pre `pos <= size()`
  1938. * \note Equivalent to `find(that.data(), pos, strlen(that))`
  1939. */
  1940. constexpr std::size_t find(const Char* that, std::size_t pos) const
  1941. noexcept(false) {
  1942. return find(that, pos, folly::constexpr_strlen(that));
  1943. }
  1944. /**
  1945. * Finds the first occurrence of the first `count` characters in the buffer
  1946. * pointed to by `that` in this string, starting at offset `pos`.
  1947. * \pre `pos <= size()`
  1948. * \pre `that` points to a buffer containing at least `count` contiguous
  1949. * characters.
  1950. * \return The lowest offset `i` such that `i >= pos` and
  1951. * `0 == strncmp(data() + i, that, count)`; or `npos` if there is no such
  1952. * offset `i`.
  1953. * \throw std::out_of_range when `pos > size()`
  1954. */
  1955. constexpr std::size_t find(
  1956. const Char* that,
  1957. std::size_t pos,
  1958. std::size_t count) const noexcept(false) {
  1959. return count <= size_ - detail::fixedstring::checkOverflow(pos, size_)
  1960. ? detail::fixedstring::find_(data_, size_, that, pos, count)
  1961. : npos;
  1962. }
  1963. /**
  1964. * Finds the first occurrence of the character `ch` in this string.
  1965. * \note Equivalent to `find(&ch, 0, 1)`
  1966. */
  1967. constexpr std::size_t find(Char ch) const noexcept {
  1968. return find(ch, 0u);
  1969. }
  1970. /**
  1971. * Finds the first occurrence of the character character `c` in this string,
  1972. * starting at offset `pos`.
  1973. * \pre `pos <= size()`
  1974. * \note Equivalent to `find(&ch, pos, 1)`
  1975. */
  1976. constexpr std::size_t find(Char ch, std::size_t pos) const noexcept(false) {
  1977. using A = const Char[1u];
  1978. return 0u == size_ - detail::fixedstring::checkOverflow(pos, size_)
  1979. ? npos
  1980. : detail::fixedstring::find_(data_, size_, A{ch}, pos, 1u);
  1981. }
  1982. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  1983. * Finds the last occurrence of characters in the string
  1984. * `that` in this string.
  1985. * \note Equivalent to `rfind(that.data(), size(), that.size())`
  1986. */
  1987. template <std::size_t M>
  1988. constexpr std::size_t rfind(const BasicFixedString<Char, M>& that) const
  1989. noexcept {
  1990. return rfind(that, size_);
  1991. }
  1992. /**
  1993. * Finds the last occurrence of characters in the string
  1994. * `that` in this string, starting at offset `pos`.
  1995. * \note Equivalent to `rfind(that.data(), pos, that.size())`
  1996. */
  1997. template <std::size_t M>
  1998. constexpr std::size_t rfind(
  1999. const BasicFixedString<Char, M>& that,
  2000. std::size_t pos) const noexcept(false) {
  2001. return that.size_ <= size_
  2002. ? detail::fixedstring::rfind_(
  2003. data_,
  2004. that.data_,
  2005. folly::constexpr_min(
  2006. detail::fixedstring::checkOverflow(pos, size_),
  2007. size_ - that.size_),
  2008. that.size_)
  2009. : npos;
  2010. }
  2011. /**
  2012. * Finds the last occurrence of characters in the buffer
  2013. * pointed to by `that` in this string.
  2014. * \note Equivalent to `rfind(that, size(), strlen(that))`
  2015. */
  2016. constexpr std::size_t rfind(const Char* that) const noexcept {
  2017. return rfind(that, size_, folly::constexpr_strlen(that));
  2018. }
  2019. /**
  2020. * Finds the last occurrence of characters in the buffer
  2021. * pointed to by `that` in this string, starting at offset `pos`.
  2022. * \note Equivalent to `rfind(that, pos, strlen(that))`
  2023. */
  2024. constexpr std::size_t rfind(const Char* that, std::size_t pos) const
  2025. noexcept(false) {
  2026. return rfind(that, pos, folly::constexpr_strlen(that));
  2027. }
  2028. /**
  2029. * Finds the last occurrence of the first `count` characters in the buffer
  2030. * pointed to by `that` in this string, starting at offset `pos`.
  2031. * \pre `pos <= size()`
  2032. * \pre `that` points to a buffer containing at least `count` contiguous
  2033. * characters.
  2034. * \return The largest offset `i` such that `i <= pos` and
  2035. * `i + count <= size()` and `0 == strncmp(data() + i, that, count)`; or
  2036. * `npos` if there is no such offset `i`.
  2037. * \throw std::out_of_range when `pos > size()`
  2038. */
  2039. constexpr std::size_t rfind(
  2040. const Char* that,
  2041. std::size_t pos,
  2042. std::size_t count) const noexcept(false) {
  2043. return count <= size_
  2044. ? detail::fixedstring::rfind_(
  2045. data_,
  2046. that,
  2047. folly::constexpr_min(
  2048. detail::fixedstring::checkOverflow(pos, size_),
  2049. size_ - count),
  2050. count)
  2051. : npos;
  2052. }
  2053. /**
  2054. * Finds the last occurrence of the character character `ch` in this string.
  2055. * \note Equivalent to `rfind(&ch, size(), 1)`
  2056. */
  2057. constexpr std::size_t rfind(Char ch) const noexcept {
  2058. return rfind(ch, size_);
  2059. }
  2060. /**
  2061. * Finds the last occurrence of the character character `ch` in this string,
  2062. * starting at offset `pos`.
  2063. * \pre `pos <= size()`
  2064. * \note Equivalent to `rfind(&ch, pos, 1)`
  2065. */
  2066. constexpr std::size_t rfind(Char ch, std::size_t pos) const noexcept(false) {
  2067. using A = const Char[1u];
  2068. return 0u == size_
  2069. ? npos
  2070. : detail::fixedstring::rfind_(
  2071. data_,
  2072. A{ch},
  2073. folly::constexpr_min(
  2074. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2075. 1u);
  2076. }
  2077. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2078. * Finds the first occurrence of any character in `that` in this string.
  2079. * \note Equivalent to `find_first_of(that.data(), 0, that.size())`
  2080. */
  2081. template <std::size_t M>
  2082. constexpr std::size_t find_first_of(
  2083. const BasicFixedString<Char, M>& that) const noexcept {
  2084. return find_first_of(that, 0u);
  2085. }
  2086. /**
  2087. * Finds the first occurrence of any character in `that` in this string,
  2088. * starting at offset `pos`
  2089. * \note Equivalent to `find_first_of(that.data(), pos, that.size())`
  2090. */
  2091. template <std::size_t M>
  2092. constexpr std::size_t find_first_of(
  2093. const BasicFixedString<Char, M>& that,
  2094. std::size_t pos) const noexcept(false) {
  2095. return size_ == detail::fixedstring::checkOverflow(pos, size_)
  2096. ? npos
  2097. : detail::fixedstring::find_first_of_(
  2098. data_, size_, that.data_, pos, that.size_);
  2099. }
  2100. /**
  2101. * Finds the first occurrence of any character in the null-terminated
  2102. * character sequence pointed to by `that` in this string.
  2103. * \note Equivalent to `find_first_of(that, 0, strlen(that))`
  2104. */
  2105. constexpr std::size_t find_first_of(const Char* that) const noexcept {
  2106. return find_first_of(that, 0u, folly::constexpr_strlen(that));
  2107. }
  2108. /**
  2109. * Finds the first occurrence of any character in the null-terminated
  2110. * character sequence pointed to by `that` in this string,
  2111. * starting at offset `pos`
  2112. * \note Equivalent to `find_first_of(that, pos, strlen(that))`
  2113. */
  2114. constexpr std::size_t find_first_of(const Char* that, std::size_t pos) const
  2115. noexcept(false) {
  2116. return find_first_of(that, pos, folly::constexpr_strlen(that));
  2117. }
  2118. /**
  2119. * Finds the first occurrence of any character in the first `count` characters
  2120. * in the buffer pointed to by `that` in this string, starting at offset
  2121. * `pos`.
  2122. * \pre `pos <= size()`
  2123. * \pre `that` points to a buffer containing at least `count` contiguous
  2124. * characters.
  2125. * \return The smallest offset `i` such that `i >= pos` and
  2126. * `std::find(that, that+count, at(i)) != that+count`; or
  2127. * `npos` if there is no such offset `i`.
  2128. * \throw std::out_of_range when `pos > size()`
  2129. */
  2130. constexpr std::size_t find_first_of(
  2131. const Char* that,
  2132. std::size_t pos,
  2133. std::size_t count) const noexcept(false) {
  2134. return size_ == detail::fixedstring::checkOverflow(pos, size_)
  2135. ? npos
  2136. : detail::fixedstring::find_first_of_(data_, size_, that, pos, count);
  2137. }
  2138. /**
  2139. * Finds the first occurrence of `ch` in this string.
  2140. * \note Equivalent to `find_first_of(&ch, 0, 1)`
  2141. */
  2142. constexpr std::size_t find_first_of(Char ch) const noexcept {
  2143. return find_first_of(ch, 0u);
  2144. }
  2145. /**
  2146. * Finds the first occurrence of `ch` in this string,
  2147. * starting at offset `pos`.
  2148. * \note Equivalent to `find_first_of(&ch, pos, 1)`
  2149. */
  2150. constexpr std::size_t find_first_of(Char ch, std::size_t pos) const
  2151. noexcept(false) {
  2152. using A = const Char[1u];
  2153. return size_ == detail::fixedstring::checkOverflow(pos, size_)
  2154. ? npos
  2155. : detail::fixedstring::find_first_of_(data_, size_, A{ch}, pos, 1u);
  2156. }
  2157. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2158. * Finds the first occurrence of any character not in `that` in this string.
  2159. * \note Equivalent to `find_first_not_of(that.data(), 0, that.size())`
  2160. */
  2161. template <std::size_t M>
  2162. constexpr std::size_t find_first_not_of(
  2163. const BasicFixedString<Char, M>& that) const noexcept {
  2164. return find_first_not_of(that, 0u);
  2165. }
  2166. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2167. * Finds the first occurrence of any character not in `that` in this string.
  2168. * \note Equivalent to `find_first_not_of(that.data(), 0, that.size())`
  2169. */
  2170. template <std::size_t M>
  2171. constexpr std::size_t find_first_not_of(
  2172. const BasicFixedString<Char, M>& that,
  2173. std::size_t pos) const noexcept(false) {
  2174. return size_ == detail::fixedstring::checkOverflow(pos, size_)
  2175. ? npos
  2176. : detail::fixedstring::find_first_not_of_(
  2177. data_, size_, that.data_, pos, that.size_);
  2178. }
  2179. /**
  2180. * Finds the first occurrence of any character not in the null-terminated
  2181. * character sequence pointed to by `that` in this string.
  2182. * \note Equivalent to `find_first_not_of(that, 0, strlen(that))`
  2183. */
  2184. constexpr std::size_t find_first_not_of(const Char* that) const noexcept {
  2185. return find_first_not_of(that, 0u, folly::constexpr_strlen(that));
  2186. }
  2187. /**
  2188. * Finds the first occurrence of any character not in the null-terminated
  2189. * character sequence pointed to by `that` in this string,
  2190. * starting at offset `pos`
  2191. * \note Equivalent to `find_first_not_of(that, pos, strlen(that))`
  2192. */
  2193. constexpr std::size_t find_first_not_of(const Char* that, std::size_t pos)
  2194. const noexcept(false) {
  2195. return find_first_not_of(that, pos, folly::constexpr_strlen(that));
  2196. }
  2197. /**
  2198. * Finds the first occurrence of any character not in the first `count`
  2199. * characters in the buffer pointed to by `that` in this string, starting at
  2200. * offset `pos`.
  2201. * \pre `pos <= size()`
  2202. * \pre `that` points to a buffer containing at least `count` contiguous
  2203. * characters.
  2204. * \return The smallest offset `i` such that `i >= pos` and
  2205. * `std::find(that, that+count, at(i)) == that+count`; or
  2206. * `npos` if there is no such offset `i`.
  2207. * \throw std::out_of_range when `pos > size()`
  2208. */
  2209. constexpr std::size_t find_first_not_of(
  2210. const Char* that,
  2211. std::size_t pos,
  2212. std::size_t count) const noexcept(false) {
  2213. return size_ == detail::fixedstring::checkOverflow(pos, size_)
  2214. ? npos
  2215. : detail::fixedstring::find_first_not_of_(
  2216. data_, size_, that, pos, count);
  2217. }
  2218. /**
  2219. * Finds the first occurrence of any character other than `ch` in this string.
  2220. * \note Equivalent to `find_first_not_of(&ch, 0, 1)`
  2221. */
  2222. constexpr std::size_t find_first_not_of(Char ch) const noexcept {
  2223. return find_first_not_of(ch, 0u);
  2224. }
  2225. /**
  2226. * Finds the first occurrence of any character other than `ch` in this string,
  2227. * starting at offset `pos`.
  2228. * \note Equivalent to `find_first_not_of(&ch, pos, 1)`
  2229. */
  2230. constexpr std::size_t find_first_not_of(Char ch, std::size_t pos) const
  2231. noexcept(false) {
  2232. using A = const Char[1u];
  2233. return 1u <= size_ - detail::fixedstring::checkOverflow(pos, size_)
  2234. ? detail::fixedstring::find_first_not_of_(data_, size_, A{ch}, pos, 1u)
  2235. : npos;
  2236. }
  2237. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2238. * Finds the last occurrence of any character in `that` in this string.
  2239. * \note Equivalent to `find_last_of(that.data(), size(), that.size())`
  2240. */
  2241. template <std::size_t M>
  2242. constexpr std::size_t find_last_of(
  2243. const BasicFixedString<Char, M>& that) const noexcept {
  2244. return find_last_of(that, size_);
  2245. }
  2246. /**
  2247. * Finds the last occurrence of any character in `that` in this string,
  2248. * starting at offset `pos`
  2249. * \note Equivalent to `find_last_of(that.data(), pos, that.size())`
  2250. */
  2251. template <std::size_t M>
  2252. constexpr std::size_t find_last_of(
  2253. const BasicFixedString<Char, M>& that,
  2254. std::size_t pos) const noexcept(false) {
  2255. return 0u == size_
  2256. ? npos
  2257. : detail::fixedstring::find_last_of_(
  2258. data_,
  2259. that.data_,
  2260. folly::constexpr_min(
  2261. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2262. that.size_);
  2263. }
  2264. /**
  2265. * Finds the last occurrence of any character in the null-terminated
  2266. * character sequence pointed to by `that` in this string.
  2267. * \note Equivalent to `find_last_of(that, size(), strlen(that))`
  2268. */
  2269. constexpr std::size_t find_last_of(const Char* that) const noexcept {
  2270. return find_last_of(that, size_, folly::constexpr_strlen(that));
  2271. }
  2272. /**
  2273. * Finds the last occurrence of any character in the null-terminated
  2274. * character sequence pointed to by `that` in this string,
  2275. * starting at offset `pos`
  2276. * \note Equivalent to `find_last_of(that, pos, strlen(that))`
  2277. */
  2278. constexpr std::size_t find_last_of(const Char* that, std::size_t pos) const
  2279. noexcept(false) {
  2280. return find_last_of(that, pos, folly::constexpr_strlen(that));
  2281. }
  2282. /**
  2283. * Finds the last occurrence of any character in the first `count` characters
  2284. * in the buffer pointed to by `that` in this string, starting at offset
  2285. * `pos`.
  2286. * \pre `pos <= size()`
  2287. * \pre `that` points to a buffer containing at least `count` contiguous
  2288. * characters.
  2289. * \return The largest offset `i` such that `i <= pos` and
  2290. * `i < size()` and `std::find(that, that+count, at(i)) != that+count`; or
  2291. * `npos` if there is no such offset `i`.
  2292. * \throw std::out_of_range when `pos > size()`
  2293. */
  2294. constexpr std::size_t find_last_of(
  2295. const Char* that,
  2296. std::size_t pos,
  2297. std::size_t count) const noexcept(false) {
  2298. return 0u == size_
  2299. ? npos
  2300. : detail::fixedstring::find_last_of_(
  2301. data_,
  2302. that,
  2303. folly::constexpr_min(
  2304. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2305. count);
  2306. }
  2307. /**
  2308. * Finds the last occurrence of `ch` in this string.
  2309. * \note Equivalent to `find_last_of(&ch, size(), 1)`
  2310. */
  2311. constexpr std::size_t find_last_of(Char ch) const noexcept {
  2312. return find_last_of(ch, size_);
  2313. }
  2314. /**
  2315. * Finds the last occurrence of `ch` in this string,
  2316. * starting at offset `pos`.
  2317. * \note Equivalent to `find_last_of(&ch, pos, 1)`
  2318. */
  2319. constexpr std::size_t find_last_of(Char ch, std::size_t pos) const
  2320. noexcept(false) {
  2321. using A = const Char[1u];
  2322. return 0u == size_
  2323. ? npos
  2324. : detail::fixedstring::find_last_of_(
  2325. data_,
  2326. A{ch},
  2327. folly::constexpr_min(
  2328. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2329. 1u);
  2330. }
  2331. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2332. * Finds the last occurrence of any character not in `that` in this string.
  2333. * \note Equivalent to `find_last_not_of(that.data(), size(), that.size())`
  2334. */
  2335. template <std::size_t M>
  2336. constexpr std::size_t find_last_not_of(
  2337. const BasicFixedString<Char, M>& that) const noexcept {
  2338. return find_last_not_of(that, size_);
  2339. }
  2340. /**
  2341. * Finds the last occurrence of any character not in `that` in this string,
  2342. * starting at offset `pos`
  2343. * \note Equivalent to `find_last_not_of(that.data(), pos, that.size())`
  2344. */
  2345. template <std::size_t M>
  2346. constexpr std::size_t find_last_not_of(
  2347. const BasicFixedString<Char, M>& that,
  2348. std::size_t pos) const noexcept(false) {
  2349. return 0u == size_
  2350. ? npos
  2351. : detail::fixedstring::find_last_not_of_(
  2352. data_,
  2353. that.data_,
  2354. folly::constexpr_min(
  2355. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2356. that.size_);
  2357. }
  2358. /**
  2359. * Finds the last occurrence of any character not in the null-terminated
  2360. * character sequence pointed to by `that` in this string.
  2361. * \note Equivalent to `find_last_not_of(that, size(), strlen(that))`
  2362. */
  2363. constexpr std::size_t find_last_not_of(const Char* that) const noexcept {
  2364. return find_last_not_of(that, size_, folly::constexpr_strlen(that));
  2365. }
  2366. /**
  2367. * Finds the last occurrence of any character not in the null-terminated
  2368. * character sequence pointed to by `that` in this string,
  2369. * starting at offset `pos`
  2370. * \note Equivalent to `find_last_not_of(that, pos, strlen(that))`
  2371. */
  2372. constexpr std::size_t find_last_not_of(const Char* that, std::size_t pos)
  2373. const noexcept(false) {
  2374. return find_last_not_of(that, pos, folly::constexpr_strlen(that));
  2375. }
  2376. /**
  2377. * Finds the last occurrence of any character not in the first `count`
  2378. * characters in the buffer pointed to by `that` in this string, starting at
  2379. * offset `pos`.
  2380. * \pre `pos <= size()`
  2381. * \pre `that` points to a buffer containing at least `count` contiguous
  2382. * characters.
  2383. * \return The largest offset `i` such that `i <= pos` and
  2384. * `i < size()` and `std::find(that, that+count, at(i)) == that+count`; or
  2385. * `npos` if there is no such offset `i`.
  2386. * \throw std::out_of_range when `pos > size()`
  2387. */
  2388. constexpr std::size_t find_last_not_of(
  2389. const Char* that,
  2390. std::size_t pos,
  2391. std::size_t count) const noexcept(false) {
  2392. return 0u == size_
  2393. ? npos
  2394. : detail::fixedstring::find_last_not_of_(
  2395. data_,
  2396. that,
  2397. folly::constexpr_min(
  2398. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2399. count);
  2400. }
  2401. /**
  2402. * Finds the last occurrence of any character other than `ch` in this string.
  2403. * \note Equivalent to `find_last_not_of(&ch, size(), 1)`
  2404. */
  2405. constexpr std::size_t find_last_not_of(Char ch) const noexcept {
  2406. return find_last_not_of(ch, size_);
  2407. }
  2408. /**
  2409. * Finds the last occurrence of any character other than `ch` in this string,
  2410. * starting at offset `pos`.
  2411. * \note Equivalent to `find_last_not_of(&ch, pos, 1)`
  2412. */
  2413. constexpr std::size_t find_last_not_of(Char ch, std::size_t pos) const
  2414. noexcept(false) {
  2415. using A = const Char[1u];
  2416. return 0u == size_
  2417. ? npos
  2418. : detail::fixedstring::find_last_not_of_(
  2419. data_,
  2420. A{ch},
  2421. folly::constexpr_min(
  2422. detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
  2423. 1u);
  2424. }
  2425. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2426. * Asymmetric relational operators
  2427. */
  2428. friend constexpr bool operator==(
  2429. const Char* a,
  2430. const BasicFixedString& b) noexcept {
  2431. return detail::fixedstring::equal_(
  2432. a, folly::constexpr_strlen(a), b.data_, b.size_);
  2433. }
  2434. /**
  2435. * \overload
  2436. */
  2437. friend constexpr bool operator==(
  2438. const BasicFixedString& a,
  2439. const Char* b) noexcept {
  2440. return b == a;
  2441. }
  2442. /**
  2443. * \overload
  2444. */
  2445. friend constexpr bool operator==(
  2446. Range<const Char*> a,
  2447. const BasicFixedString& b) noexcept {
  2448. return detail::fixedstring::equal_(a.begin(), a.size(), b.data_, b.size_);
  2449. }
  2450. /**
  2451. * \overload
  2452. */
  2453. friend constexpr bool operator==(
  2454. const BasicFixedString& a,
  2455. Range<const Char*> b) noexcept {
  2456. return b == a;
  2457. }
  2458. friend constexpr bool operator!=(
  2459. const Char* a,
  2460. const BasicFixedString& b) noexcept {
  2461. return !(a == b);
  2462. }
  2463. /**
  2464. * \overload
  2465. */
  2466. friend constexpr bool operator!=(
  2467. const BasicFixedString& a,
  2468. const Char* b) noexcept {
  2469. return !(b == a);
  2470. }
  2471. /**
  2472. * \overload
  2473. */
  2474. friend constexpr bool operator!=(
  2475. Range<const Char*> a,
  2476. const BasicFixedString& b) noexcept {
  2477. return !(a == b);
  2478. }
  2479. /**
  2480. * \overload
  2481. */
  2482. friend constexpr bool operator!=(
  2483. const BasicFixedString& a,
  2484. Range<const Char*> b) noexcept {
  2485. return !(a == b);
  2486. }
  2487. friend constexpr bool operator<(
  2488. const Char* a,
  2489. const BasicFixedString& b) noexcept {
  2490. return ordering::lt ==
  2491. detail::fixedstring::compare_(
  2492. a, 0u, folly::constexpr_strlen(a), b.data_, 0u, b.size_);
  2493. }
  2494. /**
  2495. * \overload
  2496. */
  2497. friend constexpr bool operator<(
  2498. const BasicFixedString& a,
  2499. const Char* b) noexcept {
  2500. return ordering::lt ==
  2501. detail::fixedstring::compare_(
  2502. a.data_, 0u, a.size_, b, 0u, folly::constexpr_strlen(b));
  2503. }
  2504. /**
  2505. * \overload
  2506. */
  2507. friend constexpr bool operator<(
  2508. Range<const Char*> a,
  2509. const BasicFixedString& b) noexcept {
  2510. return ordering::lt ==
  2511. detail::fixedstring::compare_(
  2512. a.begin(), 0u, a.size(), b.data_, 0u, b.size_);
  2513. }
  2514. /**
  2515. * \overload
  2516. */
  2517. friend constexpr bool operator<(
  2518. const BasicFixedString& a,
  2519. Range<const Char*> b) noexcept {
  2520. return ordering::lt ==
  2521. detail::fixedstring::compare_(
  2522. a.data_, 0u, a.size_, b.begin(), 0u, b.size());
  2523. }
  2524. friend constexpr bool operator>(
  2525. const Char* a,
  2526. const BasicFixedString& b) noexcept {
  2527. return b < a;
  2528. }
  2529. /**
  2530. * \overload
  2531. */
  2532. friend constexpr bool operator>(
  2533. const BasicFixedString& a,
  2534. const Char* b) noexcept {
  2535. return b < a;
  2536. }
  2537. /**
  2538. * \overload
  2539. */
  2540. friend constexpr bool operator>(
  2541. Range<const Char*> a,
  2542. const BasicFixedString& b) noexcept {
  2543. return b < a;
  2544. }
  2545. /**
  2546. * \overload
  2547. */
  2548. friend constexpr bool operator>(
  2549. const BasicFixedString& a,
  2550. Range<const Char*> b) noexcept {
  2551. return b < a;
  2552. }
  2553. friend constexpr bool operator<=(
  2554. const Char* a,
  2555. const BasicFixedString& b) noexcept {
  2556. return !(b < a);
  2557. }
  2558. /**
  2559. * \overload
  2560. */
  2561. friend constexpr bool operator<=(
  2562. const BasicFixedString& a,
  2563. const Char* b) noexcept {
  2564. return !(b < a);
  2565. }
  2566. /**
  2567. * \overload
  2568. */
  2569. friend constexpr bool operator<=(
  2570. Range<const Char*> const& a,
  2571. const BasicFixedString& b) noexcept {
  2572. return !(b < a);
  2573. }
  2574. /**
  2575. * \overload
  2576. */
  2577. friend constexpr bool operator<=(
  2578. const BasicFixedString& a,
  2579. Range<const Char*> b) noexcept {
  2580. return !(b < a);
  2581. }
  2582. friend constexpr bool operator>=(
  2583. const Char* a,
  2584. const BasicFixedString& b) noexcept {
  2585. return !(a < b);
  2586. }
  2587. /**
  2588. * \overload
  2589. */
  2590. friend constexpr bool operator>=(
  2591. const BasicFixedString& a,
  2592. const Char* b) noexcept {
  2593. return !(a < b);
  2594. }
  2595. /**
  2596. * \overload
  2597. */
  2598. friend constexpr bool operator>=(
  2599. Range<const Char*> a,
  2600. const BasicFixedString& b) noexcept {
  2601. return !(a < b);
  2602. }
  2603. /**
  2604. * \overload
  2605. */
  2606. friend constexpr bool operator>=(
  2607. const BasicFixedString& a,
  2608. Range<const Char*> const& b) noexcept {
  2609. return !(a < b);
  2610. }
  2611. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2612. * Asymmetric concatenation
  2613. */
  2614. template <std::size_t M>
  2615. friend constexpr BasicFixedString<Char, N + M - 1u> operator+(
  2616. const Char (&a)[M],
  2617. const BasicFixedString& b) noexcept {
  2618. return detail::fixedstring::Helper::concat_<Char>(
  2619. detail::fixedstring::checkNullTerminated(a),
  2620. M - 1u,
  2621. b.data_,
  2622. b.size_,
  2623. folly::make_index_sequence<N + M - 1u>{});
  2624. }
  2625. /**
  2626. * \overload
  2627. */
  2628. template <std::size_t M>
  2629. friend constexpr BasicFixedString<Char, N + M - 1u> operator+(
  2630. const BasicFixedString& a,
  2631. const Char (&b)[M]) noexcept {
  2632. return detail::fixedstring::Helper::concat_<Char>(
  2633. a.data_,
  2634. a.size_,
  2635. detail::fixedstring::checkNullTerminated(b),
  2636. M - 1u,
  2637. folly::make_index_sequence<N + M - 1u>{});
  2638. }
  2639. /**
  2640. * \overload
  2641. */
  2642. friend constexpr BasicFixedString<Char, N + 1u> operator+(
  2643. Char a,
  2644. const BasicFixedString& b) noexcept {
  2645. using A = const Char[2u];
  2646. return detail::fixedstring::Helper::concat_<Char>(
  2647. A{a, Char(0)},
  2648. 1u,
  2649. b.data_,
  2650. b.size_,
  2651. folly::make_index_sequence<N + 1u>{});
  2652. }
  2653. /**
  2654. * \overload
  2655. */
  2656. friend constexpr BasicFixedString<Char, N + 1u> operator+(
  2657. const BasicFixedString& a,
  2658. Char b) noexcept {
  2659. using A = const Char[2u];
  2660. return detail::fixedstring::Helper::concat_<Char>(
  2661. a.data_,
  2662. a.size_,
  2663. A{b, Char(0)},
  2664. 1u,
  2665. folly::make_index_sequence<N + 1u>{});
  2666. }
  2667. };
  2668. template <class C, std::size_t N>
  2669. inline std::basic_ostream<C>& operator<<(
  2670. std::basic_ostream<C>& os,
  2671. const BasicFixedString<C, N>& string) {
  2672. using StreamSize = decltype(os.width());
  2673. os.write(string.begin(), static_cast<StreamSize>(string.size()));
  2674. return os;
  2675. }
  2676. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2677. * Symmetric relational operators
  2678. */
  2679. template <class Char, std::size_t A, std::size_t B>
  2680. constexpr bool operator==(
  2681. const BasicFixedString<Char, A>& a,
  2682. const BasicFixedString<Char, B>& b) noexcept {
  2683. return detail::fixedstring::equal_(
  2684. detail::fixedstring::Helper::data_(a),
  2685. a.size(),
  2686. detail::fixedstring::Helper::data_(b),
  2687. b.size());
  2688. }
  2689. template <class Char, std::size_t A, std::size_t B>
  2690. constexpr bool operator!=(
  2691. const BasicFixedString<Char, A>& a,
  2692. const BasicFixedString<Char, B>& b) {
  2693. return !(a == b);
  2694. }
  2695. template <class Char, std::size_t A, std::size_t B>
  2696. constexpr bool operator<(
  2697. const BasicFixedString<Char, A>& a,
  2698. const BasicFixedString<Char, B>& b) noexcept {
  2699. return ordering::lt ==
  2700. detail::fixedstring::compare_(
  2701. detail::fixedstring::Helper::data_(a),
  2702. 0u,
  2703. a.size(),
  2704. detail::fixedstring::Helper::data_(b),
  2705. 0u,
  2706. b.size());
  2707. }
  2708. template <class Char, std::size_t A, std::size_t B>
  2709. constexpr bool operator>(
  2710. const BasicFixedString<Char, A>& a,
  2711. const BasicFixedString<Char, B>& b) noexcept {
  2712. return b < a;
  2713. }
  2714. template <class Char, std::size_t A, std::size_t B>
  2715. constexpr bool operator<=(
  2716. const BasicFixedString<Char, A>& a,
  2717. const BasicFixedString<Char, B>& b) noexcept {
  2718. return !(b < a);
  2719. }
  2720. template <class Char, std::size_t A, std::size_t B>
  2721. constexpr bool operator>=(
  2722. const BasicFixedString<Char, A>& a,
  2723. const BasicFixedString<Char, B>& b) noexcept {
  2724. return !(a < b);
  2725. }
  2726. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2727. * Symmetric concatenation
  2728. */
  2729. template <class Char, std::size_t N, std::size_t M>
  2730. constexpr BasicFixedString<Char, N + M> operator+(
  2731. const BasicFixedString<Char, N>& a,
  2732. const BasicFixedString<Char, M>& b) noexcept {
  2733. return detail::fixedstring::Helper::concat_<Char>(
  2734. detail::fixedstring::Helper::data_(a),
  2735. a.size(),
  2736. detail::fixedstring::Helper::data_(b),
  2737. b.size(),
  2738. folly::make_index_sequence<N + M>{});
  2739. }
  2740. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2741. * Construct a `BasicFixedString` object from a null-terminated array of
  2742. * characters. The capacity and size of the string will be equal to one less
  2743. * than the size of the array.
  2744. * \pre `a` contains no embedded null characters.
  2745. * \pre `a[N-1] == Char(0)`
  2746. * \post For a returned string `s`, `s[i]==a[i]` for every `i` in [`0`,`N-1`].
  2747. */
  2748. template <class Char, std::size_t N>
  2749. constexpr BasicFixedString<Char, N - 1u> makeFixedString(
  2750. const Char (&a)[N]) noexcept {
  2751. return {a};
  2752. }
  2753. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  2754. * Swap function
  2755. */
  2756. template <class Char, std::size_t N>
  2757. FOLLY_CPP14_CONSTEXPR void swap(
  2758. BasicFixedString<Char, N>& a,
  2759. BasicFixedString<Char, N>& b) noexcept {
  2760. a.swap(b);
  2761. }
  2762. inline namespace literals {
  2763. inline namespace string_literals {
  2764. inline namespace {
  2765. // "const std::size_t&" is so that folly::npos has the same address in every
  2766. // translation unit. This is to avoid potential violations of the ODR.
  2767. constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos;
  2768. } // namespace
  2769. #if defined(__GNUC__) && !defined(__ICC)
  2770. #pragma GCC diagnostic push
  2771. #pragma GCC diagnostic ignored "-Wpragmas"
  2772. #pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
  2773. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
  2774. * User-defined literals for creating FixedString objects from string literals
  2775. * on the compilers that support it.
  2776. *
  2777. * \par Example:
  2778. * \par
  2779. * \code
  2780. * using namespace folly::string_literals;
  2781. * constexpr auto hello = "hello world!"_fs;
  2782. * \endcode
  2783. *
  2784. * \note This requires a GNU compiler extension
  2785. * (-Wgnu-string-literal-operator-template) supported by clang and gcc,
  2786. * proposed for standardization in
  2787. * <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0424r0.pdf>.
  2788. * \par
  2789. * For portable code, prefer the suffixes `_fs4`, `_fs8`, `_fs16`, `_fs32`,
  2790. * `_fs64`, and `_fs128` for creating instances of types `FixedString<4>`,
  2791. * `FixedString<8>`, `FixedString<16>`, etc.
  2792. */
  2793. template <class Char, Char... Cs>
  2794. constexpr BasicFixedString<Char, sizeof...(Cs)> operator"" _fs() noexcept {
  2795. #if __cplusplus >= 201402L
  2796. const Char a[] = {Cs..., Char(0)};
  2797. return {+a, sizeof...(Cs)};
  2798. #else
  2799. using A = const Char[sizeof...(Cs) + 1u];
  2800. // The `+` in `+A{etc}` forces the array type to decay to a pointer
  2801. return {+A{Cs..., Char(0)}, sizeof...(Cs)};
  2802. #endif
  2803. }
  2804. #pragma GCC diagnostic pop
  2805. #endif
  2806. #define FOLLY_DEFINE_FIXED_STRING_UDL(N) \
  2807. constexpr FixedString<N> operator"" _fs##N( \
  2808. const char* that, std::size_t count) noexcept(false) { \
  2809. return {that, count}; \
  2810. } \
  2811. /**/
  2812. // Define UDLs _fs4, _fs8, _fs16, etc for FixedString<[4, 8, 16, ...]>
  2813. FOLLY_DEFINE_FIXED_STRING_UDL(4)
  2814. FOLLY_DEFINE_FIXED_STRING_UDL(8)
  2815. FOLLY_DEFINE_FIXED_STRING_UDL(16)
  2816. FOLLY_DEFINE_FIXED_STRING_UDL(32)
  2817. FOLLY_DEFINE_FIXED_STRING_UDL(64)
  2818. FOLLY_DEFINE_FIXED_STRING_UDL(128)
  2819. #undef FOLLY_DEFINE_FIXED_STRING_UDL
  2820. } // namespace string_literals
  2821. } // namespace literals
  2822. // TODO:
  2823. // // numeric conversions:
  2824. // template <std::size_t N>
  2825. // constexpr int stoi(const FixedString<N>& str, int base = 10);
  2826. // template <std::size_t N>
  2827. // constexpr unsigned stou(const FixedString<N>& str, int base = 10);
  2828. // template <std::size_t N>
  2829. // constexpr long stol(const FixedString<N>& str, int base = 10);
  2830. // template <std::size_t N>
  2831. // constexpr unsigned long stoul(const FixedString<N>& str, int base = 10;
  2832. // template <std::size_t N>
  2833. // constexpr long long stoll(const FixedString<N>& str, int base = 10);
  2834. // template <std::size_t N>
  2835. // constexpr unsigned long long stoull(const FixedString<N>& str,
  2836. // int base = 10);
  2837. // template <std::size_t N>
  2838. // constexpr float stof(const FixedString<N>& str);
  2839. // template <std::size_t N>
  2840. // constexpr double stod(const FixedString<N>& str);
  2841. // template <std::size_t N>
  2842. // constexpr long double stold(const FixedString<N>& str);
  2843. // template <int val>
  2844. // constexpr FixedString</*...*/> to_fixed_string_i() noexcept;
  2845. // template <unsigned val>
  2846. // constexpr FixedString</*...*/> to_fixed_string_u() noexcept;
  2847. // template <long val>
  2848. // constexpr FixedString</*...*/> to_fixed_string_l() noexcept;
  2849. // template <unsigned long val>
  2850. // constexpr FixedString</*...*/> to_fixed_string_ul() noexcept;
  2851. // template <long long val>
  2852. // constexpr FixedString</*...*/> to_fixed_string_ll() noexcept
  2853. // template <unsigned long long val>
  2854. // constexpr FixedString</*...*/> to_fixed_string_ull() noexcept;
  2855. } // namespace folly