FBString.h 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965
  1. /*
  2. * Copyright 2011-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: Andrei Alexandrescu (aalexandre)
  17. // String type.
  18. #pragma once
  19. #include <atomic>
  20. #include <cstddef>
  21. #include <iosfwd>
  22. #include <limits>
  23. #include <stdexcept>
  24. #include <type_traits>
  25. // This file appears in two locations: inside fbcode and in the
  26. // libstdc++ source code (when embedding fbstring as std::string).
  27. // To aid in this schizophrenic use, _LIBSTDCXX_FBSTRING is defined in
  28. // libstdc++'s c++config.h, to gate use inside fbcode v. libstdc++.
  29. #ifdef _LIBSTDCXX_FBSTRING
  30. #pragma GCC system_header
  31. #include <basic_fbstring_malloc.h> // @manual
  32. // When used as std::string replacement always disable assertions.
  33. #define FBSTRING_ASSERT(expr) /* empty */
  34. #else // !_LIBSTDCXX_FBSTRING
  35. #include <folly/CppAttributes.h>
  36. #include <folly/Portability.h>
  37. // libc++ doesn't provide this header, nor does msvc
  38. #if __has_include(<bits/c++config.h>)
  39. #include <bits/c++config.h>
  40. #endif
  41. #include <algorithm>
  42. #include <cassert>
  43. #include <cstring>
  44. #include <string>
  45. #include <utility>
  46. #include <folly/Traits.h>
  47. #include <folly/hash/Hash.h>
  48. #include <folly/lang/Exception.h>
  49. #include <folly/memory/Malloc.h>
  50. // When used in folly, assertions are not disabled.
  51. #define FBSTRING_ASSERT(expr) assert(expr)
  52. #endif
  53. // We defined these here rather than including Likely.h to avoid
  54. // redefinition errors when fbstring is imported into libstdc++.
  55. #if defined(__GNUC__) && __GNUC__ >= 4
  56. #define FBSTRING_LIKELY(x) (__builtin_expect((x), 1))
  57. #define FBSTRING_UNLIKELY(x) (__builtin_expect((x), 0))
  58. #else
  59. #define FBSTRING_LIKELY(x) (x)
  60. #define FBSTRING_UNLIKELY(x) (x)
  61. #endif
  62. FOLLY_PUSH_WARNING
  63. // Ignore shadowing warnings within this file, so includers can use -Wshadow.
  64. FOLLY_GNU_DISABLE_WARNING("-Wshadow")
  65. // GCC 4.9 has a false positive in setSmallSize (probably
  66. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124), disable
  67. // compile-time array bound checking.
  68. FOLLY_GNU_DISABLE_WARNING("-Warray-bounds")
  69. // FBString cannot use throw when replacing std::string, though it may still
  70. // use folly::throw_exception
  71. // nolint
  72. #define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW
  73. #ifdef _LIBSTDCXX_FBSTRING
  74. #define FOLLY_FBSTRING_BEGIN_NAMESPACE \
  75. namespace std _GLIBCXX_VISIBILITY(default) { \
  76. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  77. #define FOLLY_FBSTRING_END_NAMESPACE \
  78. _GLIBCXX_END_NAMESPACE_VERSION \
  79. } // namespace std
  80. #else
  81. #define FOLLY_FBSTRING_BEGIN_NAMESPACE namespace folly {
  82. #define FOLLY_FBSTRING_END_NAMESPACE } // namespace folly
  83. #endif
  84. FOLLY_FBSTRING_BEGIN_NAMESPACE
  85. #if defined(__clang__)
  86. #if __has_feature(address_sanitizer)
  87. #define FBSTRING_SANITIZE_ADDRESS
  88. #endif
  89. #elif defined(__GNUC__) && \
  90. (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ >= 5)) && \
  91. __SANITIZE_ADDRESS__
  92. #define FBSTRING_SANITIZE_ADDRESS
  93. #endif
  94. // When compiling with ASan, always heap-allocate the string even if
  95. // it would fit in-situ, so that ASan can detect access to the string
  96. // buffer after it has been invalidated (destroyed, resized, etc.).
  97. // Note that this flag doesn't remove support for in-situ strings, as
  98. // that would break ABI-compatibility and wouldn't allow linking code
  99. // compiled with this flag with code compiled without.
  100. #ifdef FBSTRING_SANITIZE_ADDRESS
  101. #define FBSTRING_DISABLE_SSO true
  102. #else
  103. #define FBSTRING_DISABLE_SSO false
  104. #endif
  105. namespace fbstring_detail {
  106. template <class InIt, class OutIt>
  107. inline std::pair<InIt, OutIt> copy_n(
  108. InIt b,
  109. typename std::iterator_traits<InIt>::difference_type n,
  110. OutIt d) {
  111. for (; n != 0; --n, ++b, ++d) {
  112. *d = *b;
  113. }
  114. return std::make_pair(b, d);
  115. }
  116. template <class Pod, class T>
  117. inline void podFill(Pod* b, Pod* e, T c) {
  118. FBSTRING_ASSERT(b && e && b <= e);
  119. constexpr auto kUseMemset = sizeof(T) == 1;
  120. if /* constexpr */ (kUseMemset) {
  121. memset(b, c, size_t(e - b));
  122. } else {
  123. auto const ee = b + ((e - b) & ~7u);
  124. for (; b != ee; b += 8) {
  125. b[0] = c;
  126. b[1] = c;
  127. b[2] = c;
  128. b[3] = c;
  129. b[4] = c;
  130. b[5] = c;
  131. b[6] = c;
  132. b[7] = c;
  133. }
  134. // Leftovers
  135. for (; b != e; ++b) {
  136. *b = c;
  137. }
  138. }
  139. }
  140. /*
  141. * Lightly structured memcpy, simplifies copying PODs and introduces
  142. * some asserts. Unfortunately using this function may cause
  143. * measurable overhead (presumably because it adjusts from a begin/end
  144. * convention to a pointer/size convention, so it does some extra
  145. * arithmetic even though the caller might have done the inverse
  146. * adaptation outside).
  147. */
  148. template <class Pod>
  149. inline void podCopy(const Pod* b, const Pod* e, Pod* d) {
  150. FBSTRING_ASSERT(b != nullptr);
  151. FBSTRING_ASSERT(e != nullptr);
  152. FBSTRING_ASSERT(d != nullptr);
  153. FBSTRING_ASSERT(e >= b);
  154. FBSTRING_ASSERT(d >= e || d + (e - b) <= b);
  155. memcpy(d, b, (e - b) * sizeof(Pod));
  156. }
  157. /*
  158. * Lightly structured memmove, simplifies copying PODs and introduces
  159. * some asserts
  160. */
  161. template <class Pod>
  162. inline void podMove(const Pod* b, const Pod* e, Pod* d) {
  163. FBSTRING_ASSERT(e >= b);
  164. memmove(d, b, (e - b) * sizeof(*b));
  165. }
  166. // always inline
  167. #if defined(__GNUC__) // Clang also defines __GNUC__
  168. #define FBSTRING_ALWAYS_INLINE inline __attribute__((__always_inline__))
  169. #elif defined(_MSC_VER)
  170. #define FBSTRING_ALWAYS_INLINE __forceinline
  171. #else
  172. #define FBSTRING_ALWAYS_INLINE inline
  173. #endif
  174. [[noreturn]] FBSTRING_ALWAYS_INLINE void assume_unreachable() {
  175. #if defined(__GNUC__) // Clang also defines __GNUC__
  176. __builtin_unreachable();
  177. #elif defined(_MSC_VER)
  178. __assume(0);
  179. #else
  180. // Well, it's better than nothing.
  181. std::abort();
  182. #endif
  183. }
  184. } // namespace fbstring_detail
  185. /**
  186. * Defines a special acquisition method for constructing fbstring
  187. * objects. AcquireMallocatedString means that the user passes a
  188. * pointer to a malloc-allocated string that the fbstring object will
  189. * take into custody.
  190. */
  191. enum class AcquireMallocatedString {};
  192. /*
  193. * fbstring_core_model is a mock-up type that defines all required
  194. * signatures of a fbstring core. The fbstring class itself uses such
  195. * a core object to implement all of the numerous member functions
  196. * required by the standard.
  197. *
  198. * If you want to define a new core, copy the definition below and
  199. * implement the primitives. Then plug the core into basic_fbstring as
  200. * a template argument.
  201. template <class Char>
  202. class fbstring_core_model {
  203. public:
  204. fbstring_core_model();
  205. fbstring_core_model(const fbstring_core_model &);
  206. ~fbstring_core_model();
  207. // Returns a pointer to string's buffer (currently only contiguous
  208. // strings are supported). The pointer is guaranteed to be valid
  209. // until the next call to a non-const member function.
  210. const Char * data() const;
  211. // Much like data(), except the string is prepared to support
  212. // character-level changes. This call is a signal for
  213. // e.g. reference-counted implementation to fork the data. The
  214. // pointer is guaranteed to be valid until the next call to a
  215. // non-const member function.
  216. Char* mutableData();
  217. // Returns a pointer to string's buffer and guarantees that a
  218. // readable '\0' lies right after the buffer. The pointer is
  219. // guaranteed to be valid until the next call to a non-const member
  220. // function.
  221. const Char * c_str() const;
  222. // Shrinks the string by delta characters. Asserts that delta <=
  223. // size().
  224. void shrink(size_t delta);
  225. // Expands the string by delta characters (i.e. after this call
  226. // size() will report the old size() plus delta) but without
  227. // initializing the expanded region. The expanded region is
  228. // zero-terminated. Returns a pointer to the memory to be
  229. // initialized (the beginning of the expanded portion). The caller
  230. // is expected to fill the expanded area appropriately.
  231. // If expGrowth is true, exponential growth is guaranteed.
  232. // It is not guaranteed not to reallocate even if size() + delta <
  233. // capacity(), so all references to the buffer are invalidated.
  234. Char* expandNoinit(size_t delta, bool expGrowth);
  235. // Expands the string by one character and sets the last character
  236. // to c.
  237. void push_back(Char c);
  238. // Returns the string's size.
  239. size_t size() const;
  240. // Returns the string's capacity, i.e. maximum size that the string
  241. // can grow to without reallocation. Note that for reference counted
  242. // strings that's technically a lie - even assigning characters
  243. // within the existing size would cause a reallocation.
  244. size_t capacity() const;
  245. // Returns true if the data underlying the string is actually shared
  246. // across multiple strings (in a refcounted fashion).
  247. bool isShared() const;
  248. // Makes sure that at least minCapacity characters are available for
  249. // the string without reallocation. For reference-counted strings,
  250. // it should fork the data even if minCapacity < size().
  251. void reserve(size_t minCapacity);
  252. private:
  253. // Do not implement
  254. fbstring_core_model& operator=(const fbstring_core_model &);
  255. };
  256. */
  257. /**
  258. * This is the core of the string. The code should work on 32- and
  259. * 64-bit and both big- and little-endianan architectures with any
  260. * Char size.
  261. *
  262. * The storage is selected as follows (assuming we store one-byte
  263. * characters on a 64-bit machine): (a) "small" strings between 0 and
  264. * 23 chars are stored in-situ without allocation (the rightmost byte
  265. * stores the size); (b) "medium" strings from 24 through 254 chars
  266. * are stored in malloc-allocated memory that is copied eagerly; (c)
  267. * "large" strings of 255 chars and above are stored in a similar
  268. * structure as medium arrays, except that the string is
  269. * reference-counted and copied lazily. the reference count is
  270. * allocated right before the character array.
  271. *
  272. * The discriminator between these three strategies sits in two
  273. * bits of the rightmost char of the storage:
  274. * - If neither is set, then the string is small. Its length is represented by
  275. * the lower-order bits on little-endian or the high-order bits on big-endian
  276. * of that rightmost character. The value of these six bits is
  277. * `maxSmallSize - size`, so this quantity must be subtracted from
  278. * `maxSmallSize` to compute the `size` of the string (see `smallSize()`).
  279. * This scheme ensures that when `size == `maxSmallSize`, the last byte in the
  280. * storage is \0. This way, storage will be a null-terminated sequence of
  281. * bytes, even if all 23 bytes of data are used on a 64-bit architecture.
  282. * This enables `c_str()` and `data()` to simply return a pointer to the
  283. * storage.
  284. *
  285. * - If the MSb is set, the string is medium width.
  286. *
  287. * - If the second MSb is set, then the string is large. On little-endian,
  288. * these 2 bits are the 2 MSbs of MediumLarge::capacity_, while on
  289. * big-endian, these 2 bits are the 2 LSbs. This keeps both little-endian
  290. * and big-endian fbstring_core equivalent with merely different ops used
  291. * to extract capacity/category.
  292. */
  293. template <class Char>
  294. class fbstring_core {
  295. protected:
  296. // It's MSVC, so we just have to guess ... and allow an override
  297. #ifdef _MSC_VER
  298. #ifdef FOLLY_ENDIAN_BE
  299. static constexpr auto kIsLittleEndian = false;
  300. #else
  301. static constexpr auto kIsLittleEndian = true;
  302. #endif
  303. #else
  304. static constexpr auto kIsLittleEndian =
  305. __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
  306. #endif
  307. public:
  308. fbstring_core() noexcept {
  309. reset();
  310. }
  311. fbstring_core(const fbstring_core& rhs) {
  312. FBSTRING_ASSERT(&rhs != this);
  313. switch (rhs.category()) {
  314. case Category::isSmall:
  315. copySmall(rhs);
  316. break;
  317. case Category::isMedium:
  318. copyMedium(rhs);
  319. break;
  320. case Category::isLarge:
  321. copyLarge(rhs);
  322. break;
  323. default:
  324. fbstring_detail::assume_unreachable();
  325. }
  326. FBSTRING_ASSERT(size() == rhs.size());
  327. FBSTRING_ASSERT(memcmp(data(), rhs.data(), size() * sizeof(Char)) == 0);
  328. }
  329. fbstring_core(fbstring_core&& goner) noexcept {
  330. // Take goner's guts
  331. ml_ = goner.ml_;
  332. // Clean goner's carcass
  333. goner.reset();
  334. }
  335. fbstring_core(
  336. const Char* const data,
  337. const size_t size,
  338. bool disableSSO = FBSTRING_DISABLE_SSO) {
  339. if (!disableSSO && size <= maxSmallSize) {
  340. initSmall(data, size);
  341. } else if (size <= maxMediumSize) {
  342. initMedium(data, size);
  343. } else {
  344. initLarge(data, size);
  345. }
  346. FBSTRING_ASSERT(this->size() == size);
  347. FBSTRING_ASSERT(
  348. size == 0 || memcmp(this->data(), data, size * sizeof(Char)) == 0);
  349. }
  350. ~fbstring_core() noexcept {
  351. if (category() == Category::isSmall) {
  352. return;
  353. }
  354. destroyMediumLarge();
  355. }
  356. // Snatches a previously mallocated string. The parameter "size"
  357. // is the size of the string, and the parameter "allocatedSize"
  358. // is the size of the mallocated block. The string must be
  359. // \0-terminated, so allocatedSize >= size + 1 and data[size] == '\0'.
  360. //
  361. // So if you want a 2-character string, pass malloc(3) as "data",
  362. // pass 2 as "size", and pass 3 as "allocatedSize".
  363. fbstring_core(
  364. Char* const data,
  365. const size_t size,
  366. const size_t allocatedSize,
  367. AcquireMallocatedString) {
  368. if (size > 0) {
  369. FBSTRING_ASSERT(allocatedSize >= size + 1);
  370. FBSTRING_ASSERT(data[size] == '\0');
  371. // Use the medium string storage
  372. ml_.data_ = data;
  373. ml_.size_ = size;
  374. // Don't forget about null terminator
  375. ml_.setCapacity(allocatedSize - 1, Category::isMedium);
  376. } else {
  377. // No need for the memory
  378. free(data);
  379. reset();
  380. }
  381. }
  382. // swap below doesn't test whether &rhs == this (and instead
  383. // potentially does extra work) on the premise that the rarity of
  384. // that situation actually makes the check more expensive than is
  385. // worth.
  386. void swap(fbstring_core& rhs) {
  387. auto const t = ml_;
  388. ml_ = rhs.ml_;
  389. rhs.ml_ = t;
  390. }
  391. // In C++11 data() and c_str() are 100% equivalent.
  392. const Char* data() const {
  393. return c_str();
  394. }
  395. Char* mutableData() {
  396. switch (category()) {
  397. case Category::isSmall:
  398. return small_;
  399. case Category::isMedium:
  400. return ml_.data_;
  401. case Category::isLarge:
  402. return mutableDataLarge();
  403. }
  404. fbstring_detail::assume_unreachable();
  405. }
  406. const Char* c_str() const {
  407. const Char* ptr = ml_.data_;
  408. // With this syntax, GCC and Clang generate a CMOV instead of a branch.
  409. ptr = (category() == Category::isSmall) ? small_ : ptr;
  410. return ptr;
  411. }
  412. void shrink(const size_t delta) {
  413. if (category() == Category::isSmall) {
  414. shrinkSmall(delta);
  415. } else if (
  416. category() == Category::isMedium || RefCounted::refs(ml_.data_) == 1) {
  417. shrinkMedium(delta);
  418. } else {
  419. shrinkLarge(delta);
  420. }
  421. }
  422. FOLLY_MALLOC_NOINLINE
  423. void reserve(size_t minCapacity, bool disableSSO = FBSTRING_DISABLE_SSO) {
  424. switch (category()) {
  425. case Category::isSmall:
  426. reserveSmall(minCapacity, disableSSO);
  427. break;
  428. case Category::isMedium:
  429. reserveMedium(minCapacity);
  430. break;
  431. case Category::isLarge:
  432. reserveLarge(minCapacity);
  433. break;
  434. default:
  435. fbstring_detail::assume_unreachable();
  436. }
  437. FBSTRING_ASSERT(capacity() >= minCapacity);
  438. }
  439. Char* expandNoinit(
  440. const size_t delta,
  441. bool expGrowth = false,
  442. bool disableSSO = FBSTRING_DISABLE_SSO);
  443. void push_back(Char c) {
  444. *expandNoinit(1, /* expGrowth = */ true) = c;
  445. }
  446. size_t size() const {
  447. size_t ret = ml_.size_;
  448. if /* constexpr */ (kIsLittleEndian) {
  449. // We can save a couple instructions, because the category is
  450. // small iff the last char, as unsigned, is <= maxSmallSize.
  451. typedef typename std::make_unsigned<Char>::type UChar;
  452. auto maybeSmallSize = size_t(maxSmallSize) -
  453. size_t(static_cast<UChar>(small_[maxSmallSize]));
  454. // With this syntax, GCC and Clang generate a CMOV instead of a branch.
  455. ret = (static_cast<ssize_t>(maybeSmallSize) >= 0) ? maybeSmallSize : ret;
  456. } else {
  457. ret = (category() == Category::isSmall) ? smallSize() : ret;
  458. }
  459. return ret;
  460. }
  461. size_t capacity() const {
  462. switch (category()) {
  463. case Category::isSmall:
  464. return maxSmallSize;
  465. case Category::isLarge:
  466. // For large-sized strings, a multi-referenced chunk has no
  467. // available capacity. This is because any attempt to append
  468. // data would trigger a new allocation.
  469. if (RefCounted::refs(ml_.data_) > 1) {
  470. return ml_.size_;
  471. }
  472. break;
  473. default:
  474. break;
  475. }
  476. return ml_.capacity();
  477. }
  478. bool isShared() const {
  479. return category() == Category::isLarge && RefCounted::refs(ml_.data_) > 1;
  480. }
  481. private:
  482. // Disabled
  483. fbstring_core& operator=(const fbstring_core& rhs);
  484. void reset() {
  485. setSmallSize(0);
  486. }
  487. FOLLY_MALLOC_NOINLINE void destroyMediumLarge() noexcept {
  488. auto const c = category();
  489. FBSTRING_ASSERT(c != Category::isSmall);
  490. if (c == Category::isMedium) {
  491. free(ml_.data_);
  492. } else {
  493. RefCounted::decrementRefs(ml_.data_);
  494. }
  495. }
  496. struct RefCounted {
  497. std::atomic<size_t> refCount_;
  498. Char data_[1];
  499. constexpr static size_t getDataOffset() {
  500. return offsetof(RefCounted, data_);
  501. }
  502. static RefCounted* fromData(Char* p) {
  503. return static_cast<RefCounted*>(static_cast<void*>(
  504. static_cast<unsigned char*>(static_cast<void*>(p)) -
  505. getDataOffset()));
  506. }
  507. static size_t refs(Char* p) {
  508. return fromData(p)->refCount_.load(std::memory_order_acquire);
  509. }
  510. static void incrementRefs(Char* p) {
  511. fromData(p)->refCount_.fetch_add(1, std::memory_order_acq_rel);
  512. }
  513. static void decrementRefs(Char* p) {
  514. auto const dis = fromData(p);
  515. size_t oldcnt = dis->refCount_.fetch_sub(1, std::memory_order_acq_rel);
  516. FBSTRING_ASSERT(oldcnt > 0);
  517. if (oldcnt == 1) {
  518. free(dis);
  519. }
  520. }
  521. static RefCounted* create(size_t* size) {
  522. const size_t allocSize =
  523. goodMallocSize(getDataOffset() + (*size + 1) * sizeof(Char));
  524. auto result = static_cast<RefCounted*>(checkedMalloc(allocSize));
  525. result->refCount_.store(1, std::memory_order_release);
  526. *size = (allocSize - getDataOffset()) / sizeof(Char) - 1;
  527. return result;
  528. }
  529. static RefCounted* create(const Char* data, size_t* size) {
  530. const size_t effectiveSize = *size;
  531. auto result = create(size);
  532. if (FBSTRING_LIKELY(effectiveSize > 0)) {
  533. fbstring_detail::podCopy(data, data + effectiveSize, result->data_);
  534. }
  535. return result;
  536. }
  537. static RefCounted* reallocate(
  538. Char* const data,
  539. const size_t currentSize,
  540. const size_t currentCapacity,
  541. size_t* newCapacity) {
  542. FBSTRING_ASSERT(*newCapacity > 0 && *newCapacity > currentSize);
  543. const size_t allocNewCapacity =
  544. goodMallocSize(getDataOffset() + (*newCapacity + 1) * sizeof(Char));
  545. auto const dis = fromData(data);
  546. FBSTRING_ASSERT(dis->refCount_.load(std::memory_order_acquire) == 1);
  547. auto result = static_cast<RefCounted*>(smartRealloc(
  548. dis,
  549. getDataOffset() + (currentSize + 1) * sizeof(Char),
  550. getDataOffset() + (currentCapacity + 1) * sizeof(Char),
  551. allocNewCapacity));
  552. FBSTRING_ASSERT(result->refCount_.load(std::memory_order_acquire) == 1);
  553. *newCapacity = (allocNewCapacity - getDataOffset()) / sizeof(Char) - 1;
  554. return result;
  555. }
  556. };
  557. typedef uint8_t category_type;
  558. enum class Category : category_type {
  559. isSmall = 0,
  560. isMedium = kIsLittleEndian ? 0x80 : 0x2,
  561. isLarge = kIsLittleEndian ? 0x40 : 0x1,
  562. };
  563. Category category() const {
  564. // works for both big-endian and little-endian
  565. return static_cast<Category>(bytes_[lastChar] & categoryExtractMask);
  566. }
  567. struct MediumLarge {
  568. Char* data_;
  569. size_t size_;
  570. size_t capacity_;
  571. size_t capacity() const {
  572. return kIsLittleEndian ? capacity_ & capacityExtractMask : capacity_ >> 2;
  573. }
  574. void setCapacity(size_t cap, Category cat) {
  575. capacity_ = kIsLittleEndian
  576. ? cap | (static_cast<size_t>(cat) << kCategoryShift)
  577. : (cap << 2) | static_cast<size_t>(cat);
  578. }
  579. };
  580. union {
  581. uint8_t bytes_[sizeof(MediumLarge)]; // For accessing the last byte.
  582. Char small_[sizeof(MediumLarge) / sizeof(Char)];
  583. MediumLarge ml_;
  584. };
  585. constexpr static size_t lastChar = sizeof(MediumLarge) - 1;
  586. constexpr static size_t maxSmallSize = lastChar / sizeof(Char);
  587. constexpr static size_t maxMediumSize = 254 / sizeof(Char);
  588. constexpr static uint8_t categoryExtractMask = kIsLittleEndian ? 0xC0 : 0x3;
  589. constexpr static size_t kCategoryShift = (sizeof(size_t) - 1) * 8;
  590. constexpr static size_t capacityExtractMask = kIsLittleEndian
  591. ? ~(size_t(categoryExtractMask) << kCategoryShift)
  592. : 0x0 /* unused */;
  593. static_assert(
  594. !(sizeof(MediumLarge) % sizeof(Char)),
  595. "Corrupt memory layout for fbstring.");
  596. size_t smallSize() const {
  597. FBSTRING_ASSERT(category() == Category::isSmall);
  598. constexpr auto shift = kIsLittleEndian ? 0 : 2;
  599. auto smallShifted = static_cast<size_t>(small_[maxSmallSize]) >> shift;
  600. FBSTRING_ASSERT(static_cast<size_t>(maxSmallSize) >= smallShifted);
  601. return static_cast<size_t>(maxSmallSize) - smallShifted;
  602. }
  603. void setSmallSize(size_t s) {
  604. // Warning: this should work with uninitialized strings too,
  605. // so don't assume anything about the previous value of
  606. // small_[maxSmallSize].
  607. FBSTRING_ASSERT(s <= maxSmallSize);
  608. constexpr auto shift = kIsLittleEndian ? 0 : 2;
  609. small_[maxSmallSize] = char((maxSmallSize - s) << shift);
  610. small_[s] = '\0';
  611. FBSTRING_ASSERT(category() == Category::isSmall && size() == s);
  612. }
  613. void copySmall(const fbstring_core&);
  614. void copyMedium(const fbstring_core&);
  615. void copyLarge(const fbstring_core&);
  616. void initSmall(const Char* data, size_t size);
  617. void initMedium(const Char* data, size_t size);
  618. void initLarge(const Char* data, size_t size);
  619. void reserveSmall(size_t minCapacity, bool disableSSO);
  620. void reserveMedium(size_t minCapacity);
  621. void reserveLarge(size_t minCapacity);
  622. void shrinkSmall(size_t delta);
  623. void shrinkMedium(size_t delta);
  624. void shrinkLarge(size_t delta);
  625. void unshare(size_t minCapacity = 0);
  626. Char* mutableDataLarge();
  627. };
  628. template <class Char>
  629. inline void fbstring_core<Char>::copySmall(const fbstring_core& rhs) {
  630. static_assert(offsetof(MediumLarge, data_) == 0, "fbstring layout failure");
  631. static_assert(
  632. offsetof(MediumLarge, size_) == sizeof(ml_.data_),
  633. "fbstring layout failure");
  634. static_assert(
  635. offsetof(MediumLarge, capacity_) == 2 * sizeof(ml_.data_),
  636. "fbstring layout failure");
  637. // Just write the whole thing, don't look at details. In
  638. // particular we need to copy capacity anyway because we want
  639. // to set the size (don't forget that the last character,
  640. // which stores a short string's length, is shared with the
  641. // ml_.capacity field).
  642. ml_ = rhs.ml_;
  643. FBSTRING_ASSERT(
  644. category() == Category::isSmall && this->size() == rhs.size());
  645. }
  646. template <class Char>
  647. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::copyMedium(
  648. const fbstring_core& rhs) {
  649. // Medium strings are copied eagerly. Don't forget to allocate
  650. // one extra Char for the null terminator.
  651. auto const allocSize = goodMallocSize((1 + rhs.ml_.size_) * sizeof(Char));
  652. ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize));
  653. // Also copies terminator.
  654. fbstring_detail::podCopy(
  655. rhs.ml_.data_, rhs.ml_.data_ + rhs.ml_.size_ + 1, ml_.data_);
  656. ml_.size_ = rhs.ml_.size_;
  657. ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium);
  658. FBSTRING_ASSERT(category() == Category::isMedium);
  659. }
  660. template <class Char>
  661. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::copyLarge(
  662. const fbstring_core& rhs) {
  663. // Large strings are just refcounted
  664. ml_ = rhs.ml_;
  665. RefCounted::incrementRefs(ml_.data_);
  666. FBSTRING_ASSERT(category() == Category::isLarge && size() == rhs.size());
  667. }
  668. // Small strings are bitblitted
  669. template <class Char>
  670. inline void fbstring_core<Char>::initSmall(
  671. const Char* const data,
  672. const size_t size) {
  673. // Layout is: Char* data_, size_t size_, size_t capacity_
  674. static_assert(
  675. sizeof(*this) == sizeof(Char*) + 2 * sizeof(size_t),
  676. "fbstring has unexpected size");
  677. static_assert(
  678. sizeof(Char*) == sizeof(size_t), "fbstring size assumption violation");
  679. // sizeof(size_t) must be a power of 2
  680. static_assert(
  681. (sizeof(size_t) & (sizeof(size_t) - 1)) == 0,
  682. "fbstring size assumption violation");
  683. // If data is aligned, use fast word-wise copying. Otherwise,
  684. // use conservative memcpy.
  685. // The word-wise path reads bytes which are outside the range of
  686. // the string, and makes ASan unhappy, so we disable it when
  687. // compiling with ASan.
  688. #ifndef FBSTRING_SANITIZE_ADDRESS
  689. if ((reinterpret_cast<size_t>(data) & (sizeof(size_t) - 1)) == 0) {
  690. const size_t byteSize = size * sizeof(Char);
  691. constexpr size_t wordWidth = sizeof(size_t);
  692. switch ((byteSize + wordWidth - 1) / wordWidth) { // Number of words.
  693. case 3:
  694. ml_.capacity_ = reinterpret_cast<const size_t*>(data)[2];
  695. FOLLY_FALLTHROUGH;
  696. case 2:
  697. ml_.size_ = reinterpret_cast<const size_t*>(data)[1];
  698. FOLLY_FALLTHROUGH;
  699. case 1:
  700. ml_.data_ = *reinterpret_cast<Char**>(const_cast<Char*>(data));
  701. FOLLY_FALLTHROUGH;
  702. case 0:
  703. break;
  704. }
  705. } else
  706. #endif
  707. {
  708. if (size != 0) {
  709. fbstring_detail::podCopy(data, data + size, small_);
  710. }
  711. }
  712. setSmallSize(size);
  713. }
  714. template <class Char>
  715. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::initMedium(
  716. const Char* const data,
  717. const size_t size) {
  718. // Medium strings are allocated normally. Don't forget to
  719. // allocate one extra Char for the terminating null.
  720. auto const allocSize = goodMallocSize((1 + size) * sizeof(Char));
  721. ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize));
  722. if (FBSTRING_LIKELY(size > 0)) {
  723. fbstring_detail::podCopy(data, data + size, ml_.data_);
  724. }
  725. ml_.size_ = size;
  726. ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium);
  727. ml_.data_[size] = '\0';
  728. }
  729. template <class Char>
  730. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::initLarge(
  731. const Char* const data,
  732. const size_t size) {
  733. // Large strings are allocated differently
  734. size_t effectiveCapacity = size;
  735. auto const newRC = RefCounted::create(data, &effectiveCapacity);
  736. ml_.data_ = newRC->data_;
  737. ml_.size_ = size;
  738. ml_.setCapacity(effectiveCapacity, Category::isLarge);
  739. ml_.data_[size] = '\0';
  740. }
  741. template <class Char>
  742. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::unshare(
  743. size_t minCapacity) {
  744. FBSTRING_ASSERT(category() == Category::isLarge);
  745. size_t effectiveCapacity = std::max(minCapacity, ml_.capacity());
  746. auto const newRC = RefCounted::create(&effectiveCapacity);
  747. // If this fails, someone placed the wrong capacity in an
  748. // fbstring.
  749. FBSTRING_ASSERT(effectiveCapacity >= ml_.capacity());
  750. // Also copies terminator.
  751. fbstring_detail::podCopy(ml_.data_, ml_.data_ + ml_.size_ + 1, newRC->data_);
  752. RefCounted::decrementRefs(ml_.data_);
  753. ml_.data_ = newRC->data_;
  754. ml_.setCapacity(effectiveCapacity, Category::isLarge);
  755. // size_ remains unchanged.
  756. }
  757. template <class Char>
  758. inline Char* fbstring_core<Char>::mutableDataLarge() {
  759. FBSTRING_ASSERT(category() == Category::isLarge);
  760. if (RefCounted::refs(ml_.data_) > 1) { // Ensure unique.
  761. unshare();
  762. }
  763. return ml_.data_;
  764. }
  765. template <class Char>
  766. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveLarge(
  767. size_t minCapacity) {
  768. FBSTRING_ASSERT(category() == Category::isLarge);
  769. if (RefCounted::refs(ml_.data_) > 1) { // Ensure unique
  770. // We must make it unique regardless; in-place reallocation is
  771. // useless if the string is shared. In order to not surprise
  772. // people, reserve the new block at current capacity or
  773. // more. That way, a string's capacity never shrinks after a
  774. // call to reserve.
  775. unshare(minCapacity);
  776. } else {
  777. // String is not shared, so let's try to realloc (if needed)
  778. if (minCapacity > ml_.capacity()) {
  779. // Asking for more memory
  780. auto const newRC = RefCounted::reallocate(
  781. ml_.data_, ml_.size_, ml_.capacity(), &minCapacity);
  782. ml_.data_ = newRC->data_;
  783. ml_.setCapacity(minCapacity, Category::isLarge);
  784. }
  785. FBSTRING_ASSERT(capacity() >= minCapacity);
  786. }
  787. }
  788. template <class Char>
  789. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveMedium(
  790. const size_t minCapacity) {
  791. FBSTRING_ASSERT(category() == Category::isMedium);
  792. // String is not shared
  793. if (minCapacity <= ml_.capacity()) {
  794. return; // nothing to do, there's enough room
  795. }
  796. if (minCapacity <= maxMediumSize) {
  797. // Keep the string at medium size. Don't forget to allocate
  798. // one extra Char for the terminating null.
  799. size_t capacityBytes = goodMallocSize((1 + minCapacity) * sizeof(Char));
  800. // Also copies terminator.
  801. ml_.data_ = static_cast<Char*>(smartRealloc(
  802. ml_.data_,
  803. (ml_.size_ + 1) * sizeof(Char),
  804. (ml_.capacity() + 1) * sizeof(Char),
  805. capacityBytes));
  806. ml_.setCapacity(capacityBytes / sizeof(Char) - 1, Category::isMedium);
  807. } else {
  808. // Conversion from medium to large string
  809. fbstring_core nascent;
  810. // Will recurse to another branch of this function
  811. nascent.reserve(minCapacity);
  812. nascent.ml_.size_ = ml_.size_;
  813. // Also copies terminator.
  814. fbstring_detail::podCopy(
  815. ml_.data_, ml_.data_ + ml_.size_ + 1, nascent.ml_.data_);
  816. nascent.swap(*this);
  817. FBSTRING_ASSERT(capacity() >= minCapacity);
  818. }
  819. }
  820. template <class Char>
  821. FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveSmall(
  822. size_t minCapacity,
  823. const bool disableSSO) {
  824. FBSTRING_ASSERT(category() == Category::isSmall);
  825. if (!disableSSO && minCapacity <= maxSmallSize) {
  826. // small
  827. // Nothing to do, everything stays put
  828. } else if (minCapacity <= maxMediumSize) {
  829. // medium
  830. // Don't forget to allocate one extra Char for the terminating null
  831. auto const allocSizeBytes =
  832. goodMallocSize((1 + minCapacity) * sizeof(Char));
  833. auto const pData = static_cast<Char*>(checkedMalloc(allocSizeBytes));
  834. auto const size = smallSize();
  835. // Also copies terminator.
  836. fbstring_detail::podCopy(small_, small_ + size + 1, pData);
  837. ml_.data_ = pData;
  838. ml_.size_ = size;
  839. ml_.setCapacity(allocSizeBytes / sizeof(Char) - 1, Category::isMedium);
  840. } else {
  841. // large
  842. auto const newRC = RefCounted::create(&minCapacity);
  843. auto const size = smallSize();
  844. // Also copies terminator.
  845. fbstring_detail::podCopy(small_, small_ + size + 1, newRC->data_);
  846. ml_.data_ = newRC->data_;
  847. ml_.size_ = size;
  848. ml_.setCapacity(minCapacity, Category::isLarge);
  849. FBSTRING_ASSERT(capacity() >= minCapacity);
  850. }
  851. }
  852. template <class Char>
  853. inline Char* fbstring_core<Char>::expandNoinit(
  854. const size_t delta,
  855. bool expGrowth, /* = false */
  856. bool disableSSO /* = FBSTRING_DISABLE_SSO */) {
  857. // Strategy is simple: make room, then change size
  858. FBSTRING_ASSERT(capacity() >= size());
  859. size_t sz, newSz;
  860. if (category() == Category::isSmall) {
  861. sz = smallSize();
  862. newSz = sz + delta;
  863. if (!disableSSO && FBSTRING_LIKELY(newSz <= maxSmallSize)) {
  864. setSmallSize(newSz);
  865. return small_ + sz;
  866. }
  867. reserveSmall(
  868. expGrowth ? std::max(newSz, 2 * maxSmallSize) : newSz, disableSSO);
  869. } else {
  870. sz = ml_.size_;
  871. newSz = sz + delta;
  872. if (FBSTRING_UNLIKELY(newSz > capacity())) {
  873. // ensures not shared
  874. reserve(expGrowth ? std::max(newSz, 1 + capacity() * 3 / 2) : newSz);
  875. }
  876. }
  877. FBSTRING_ASSERT(capacity() >= newSz);
  878. // Category can't be small - we took care of that above
  879. FBSTRING_ASSERT(
  880. category() == Category::isMedium || category() == Category::isLarge);
  881. ml_.size_ = newSz;
  882. ml_.data_[newSz] = '\0';
  883. FBSTRING_ASSERT(size() == newSz);
  884. return ml_.data_ + sz;
  885. }
  886. template <class Char>
  887. inline void fbstring_core<Char>::shrinkSmall(const size_t delta) {
  888. // Check for underflow
  889. FBSTRING_ASSERT(delta <= smallSize());
  890. setSmallSize(smallSize() - delta);
  891. }
  892. template <class Char>
  893. inline void fbstring_core<Char>::shrinkMedium(const size_t delta) {
  894. // Medium strings and unique large strings need no special
  895. // handling.
  896. FBSTRING_ASSERT(ml_.size_ >= delta);
  897. ml_.size_ -= delta;
  898. ml_.data_[ml_.size_] = '\0';
  899. }
  900. template <class Char>
  901. inline void fbstring_core<Char>::shrinkLarge(const size_t delta) {
  902. FBSTRING_ASSERT(ml_.size_ >= delta);
  903. // Shared large string, must make unique. This is because of the
  904. // durn terminator must be written, which may trample the shared
  905. // data.
  906. if (delta) {
  907. fbstring_core(ml_.data_, ml_.size_ - delta).swap(*this);
  908. }
  909. // No need to write the terminator.
  910. }
  911. #ifndef _LIBSTDCXX_FBSTRING
  912. /**
  913. * Dummy fbstring core that uses an actual std::string. This doesn't
  914. * make any sense - it's just for testing purposes.
  915. */
  916. template <class Char>
  917. class dummy_fbstring_core {
  918. public:
  919. dummy_fbstring_core() {}
  920. dummy_fbstring_core(const dummy_fbstring_core& another)
  921. : backend_(another.backend_) {}
  922. dummy_fbstring_core(const Char* s, size_t n) : backend_(s, n) {}
  923. void swap(dummy_fbstring_core& rhs) {
  924. backend_.swap(rhs.backend_);
  925. }
  926. const Char* data() const {
  927. return backend_.data();
  928. }
  929. Char* mutableData() {
  930. return const_cast<Char*>(backend_.data());
  931. }
  932. void shrink(size_t delta) {
  933. FBSTRING_ASSERT(delta <= size());
  934. backend_.resize(size() - delta);
  935. }
  936. Char* expandNoinit(size_t delta) {
  937. auto const sz = size();
  938. backend_.resize(size() + delta);
  939. return backend_.data() + sz;
  940. }
  941. void push_back(Char c) {
  942. backend_.push_back(c);
  943. }
  944. size_t size() const {
  945. return backend_.size();
  946. }
  947. size_t capacity() const {
  948. return backend_.capacity();
  949. }
  950. bool isShared() const {
  951. return false;
  952. }
  953. void reserve(size_t minCapacity) {
  954. backend_.reserve(minCapacity);
  955. }
  956. private:
  957. std::basic_string<Char> backend_;
  958. };
  959. #endif // !_LIBSTDCXX_FBSTRING
  960. /**
  961. * This is the basic_string replacement. For conformity,
  962. * basic_fbstring takes the same template parameters, plus the last
  963. * one which is the core.
  964. */
  965. #ifdef _LIBSTDCXX_FBSTRING
  966. template <typename E, class T, class A, class Storage>
  967. #else
  968. template <
  969. typename E,
  970. class T = std::char_traits<E>,
  971. class A = std::allocator<E>,
  972. class Storage = fbstring_core<E>>
  973. #endif
  974. class basic_fbstring {
  975. template <typename Ex, typename... Args>
  976. FOLLY_ALWAYS_INLINE static void enforce(bool condition, Args&&... args) {
  977. if (!condition) {
  978. throw_exception<Ex>(static_cast<Args&&>(args)...);
  979. }
  980. }
  981. bool isSane() const {
  982. return begin() <= end() && empty() == (size() == 0) &&
  983. empty() == (begin() == end()) && size() <= max_size() &&
  984. capacity() <= max_size() && size() <= capacity() &&
  985. begin()[size()] == '\0';
  986. }
  987. struct Invariant {
  988. Invariant& operator=(const Invariant&) = delete;
  989. explicit Invariant(const basic_fbstring& s) noexcept : s_(s) {
  990. FBSTRING_ASSERT(s_.isSane());
  991. }
  992. ~Invariant() noexcept {
  993. FBSTRING_ASSERT(s_.isSane());
  994. }
  995. private:
  996. const basic_fbstring& s_;
  997. };
  998. public:
  999. // types
  1000. typedef T traits_type;
  1001. typedef typename traits_type::char_type value_type;
  1002. typedef A allocator_type;
  1003. typedef typename A::size_type size_type;
  1004. typedef typename A::difference_type difference_type;
  1005. typedef typename A::reference reference;
  1006. typedef typename A::const_reference const_reference;
  1007. typedef typename A::pointer pointer;
  1008. typedef typename A::const_pointer const_pointer;
  1009. typedef E* iterator;
  1010. typedef const E* const_iterator;
  1011. typedef std::reverse_iterator<iterator> reverse_iterator;
  1012. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  1013. static constexpr size_type npos = size_type(-1);
  1014. typedef std::true_type IsRelocatable;
  1015. private:
  1016. static void procrustes(size_type& n, size_type nmax) {
  1017. if (n > nmax) {
  1018. n = nmax;
  1019. }
  1020. }
  1021. static size_type traitsLength(const value_type* s);
  1022. public:
  1023. // C++11 21.4.2 construct/copy/destroy
  1024. // Note: while the following two constructors can be (and previously were)
  1025. // collapsed into one constructor written this way:
  1026. //
  1027. // explicit basic_fbstring(const A& a = A()) noexcept { }
  1028. //
  1029. // This can cause Clang (at least version 3.7) to fail with the error:
  1030. // "chosen constructor is explicit in copy-initialization ...
  1031. // in implicit initialization of field '(x)' with omitted initializer"
  1032. //
  1033. // if used in a struct which is default-initialized. Hence the split into
  1034. // these two separate constructors.
  1035. basic_fbstring() noexcept : basic_fbstring(A()) {}
  1036. explicit basic_fbstring(const A&) noexcept {}
  1037. basic_fbstring(const basic_fbstring& str) : store_(str.store_) {}
  1038. // Move constructor
  1039. basic_fbstring(basic_fbstring&& goner) noexcept
  1040. : store_(std::move(goner.store_)) {}
  1041. #ifndef _LIBSTDCXX_FBSTRING
  1042. // This is defined for compatibility with std::string
  1043. template <typename A2>
  1044. /* implicit */ basic_fbstring(const std::basic_string<E, T, A2>& str)
  1045. : store_(str.data(), str.size()) {}
  1046. #endif
  1047. basic_fbstring(
  1048. const basic_fbstring& str,
  1049. size_type pos,
  1050. size_type n = npos,
  1051. const A& /* a */ = A()) {
  1052. assign(str, pos, n);
  1053. }
  1054. FOLLY_MALLOC_NOINLINE
  1055. /* implicit */ basic_fbstring(const value_type* s, const A& /*a*/ = A())
  1056. : store_(s, traitsLength(s)) {}
  1057. FOLLY_MALLOC_NOINLINE
  1058. basic_fbstring(const value_type* s, size_type n, const A& /*a*/ = A())
  1059. : store_(s, n) {}
  1060. FOLLY_MALLOC_NOINLINE
  1061. basic_fbstring(size_type n, value_type c, const A& /*a*/ = A()) {
  1062. auto const pData = store_.expandNoinit(n);
  1063. fbstring_detail::podFill(pData, pData + n, c);
  1064. }
  1065. template <class InIt>
  1066. FOLLY_MALLOC_NOINLINE basic_fbstring(
  1067. InIt begin,
  1068. InIt end,
  1069. typename std::enable_if<
  1070. !std::is_same<InIt, value_type*>::value,
  1071. const A>::type& /*a*/
  1072. = A()) {
  1073. assign(begin, end);
  1074. }
  1075. // Specialization for const char*, const char*
  1076. FOLLY_MALLOC_NOINLINE
  1077. basic_fbstring(const value_type* b, const value_type* e, const A& /*a*/ = A())
  1078. : store_(b, size_type(e - b)) {}
  1079. // Nonstandard constructor
  1080. basic_fbstring(
  1081. value_type* s,
  1082. size_type n,
  1083. size_type c,
  1084. AcquireMallocatedString a)
  1085. : store_(s, n, c, a) {}
  1086. // Construction from initialization list
  1087. FOLLY_MALLOC_NOINLINE
  1088. basic_fbstring(std::initializer_list<value_type> il) {
  1089. assign(il.begin(), il.end());
  1090. }
  1091. ~basic_fbstring() noexcept {}
  1092. basic_fbstring& operator=(const basic_fbstring& lhs);
  1093. // Move assignment
  1094. basic_fbstring& operator=(basic_fbstring&& goner) noexcept;
  1095. #ifndef _LIBSTDCXX_FBSTRING
  1096. // Compatibility with std::string
  1097. template <typename A2>
  1098. basic_fbstring& operator=(const std::basic_string<E, T, A2>& rhs) {
  1099. return assign(rhs.data(), rhs.size());
  1100. }
  1101. // Compatibility with std::string
  1102. std::basic_string<E, T, A> toStdString() const {
  1103. return std::basic_string<E, T, A>(data(), size());
  1104. }
  1105. #else
  1106. // A lot of code in fbcode still uses this method, so keep it here for now.
  1107. const basic_fbstring& toStdString() const {
  1108. return *this;
  1109. }
  1110. #endif
  1111. basic_fbstring& operator=(const value_type* s) {
  1112. return assign(s);
  1113. }
  1114. // This actually goes directly against the C++ spec, but the
  1115. // value_type overload is dangerous, so we're explicitly deleting
  1116. // any overloads of operator= that could implicitly convert to
  1117. // value_type.
  1118. // Note that we do need to explicitly specify the template types because
  1119. // otherwise MSVC 2017 will aggressively pre-resolve value_type to
  1120. // traits_type::char_type, which won't compare as equal when determining
  1121. // which overload the implementation is referring to.
  1122. // Also note that MSVC 2015 Update 3 requires us to explicitly specify the
  1123. // namespace in-which to search for basic_fbstring, otherwise it tries to
  1124. // look for basic_fbstring::basic_fbstring, which is just plain wrong.
  1125. template <typename TP>
  1126. typename std::enable_if<
  1127. std::is_same<
  1128. typename std::decay<TP>::type,
  1129. typename folly::basic_fbstring<E, T, A, Storage>::value_type>::value,
  1130. basic_fbstring<E, T, A, Storage>&>::type
  1131. operator=(TP c);
  1132. basic_fbstring& operator=(std::initializer_list<value_type> il) {
  1133. return assign(il.begin(), il.end());
  1134. }
  1135. // C++11 21.4.3 iterators:
  1136. iterator begin() {
  1137. return store_.mutableData();
  1138. }
  1139. const_iterator begin() const {
  1140. return store_.data();
  1141. }
  1142. const_iterator cbegin() const {
  1143. return begin();
  1144. }
  1145. iterator end() {
  1146. return store_.mutableData() + store_.size();
  1147. }
  1148. const_iterator end() const {
  1149. return store_.data() + store_.size();
  1150. }
  1151. const_iterator cend() const {
  1152. return end();
  1153. }
  1154. reverse_iterator rbegin() {
  1155. return reverse_iterator(end());
  1156. }
  1157. const_reverse_iterator rbegin() const {
  1158. return const_reverse_iterator(end());
  1159. }
  1160. const_reverse_iterator crbegin() const {
  1161. return rbegin();
  1162. }
  1163. reverse_iterator rend() {
  1164. return reverse_iterator(begin());
  1165. }
  1166. const_reverse_iterator rend() const {
  1167. return const_reverse_iterator(begin());
  1168. }
  1169. const_reverse_iterator crend() const {
  1170. return rend();
  1171. }
  1172. // Added by C++11
  1173. // C++11 21.4.5, element access:
  1174. const value_type& front() const {
  1175. return *begin();
  1176. }
  1177. const value_type& back() const {
  1178. FBSTRING_ASSERT(!empty());
  1179. // Should be begin()[size() - 1], but that branches twice
  1180. return *(end() - 1);
  1181. }
  1182. value_type& front() {
  1183. return *begin();
  1184. }
  1185. value_type& back() {
  1186. FBSTRING_ASSERT(!empty());
  1187. // Should be begin()[size() - 1], but that branches twice
  1188. return *(end() - 1);
  1189. }
  1190. void pop_back() {
  1191. FBSTRING_ASSERT(!empty());
  1192. store_.shrink(1);
  1193. }
  1194. // C++11 21.4.4 capacity:
  1195. size_type size() const {
  1196. return store_.size();
  1197. }
  1198. size_type length() const {
  1199. return size();
  1200. }
  1201. size_type max_size() const {
  1202. return std::numeric_limits<size_type>::max();
  1203. }
  1204. void resize(size_type n, value_type c = value_type());
  1205. size_type capacity() const {
  1206. return store_.capacity();
  1207. }
  1208. void reserve(size_type res_arg = 0) {
  1209. enforce<std::length_error>(res_arg <= max_size(), "");
  1210. store_.reserve(res_arg);
  1211. }
  1212. void shrink_to_fit() {
  1213. // Shrink only if slack memory is sufficiently large
  1214. if (capacity() < size() * 3 / 2) {
  1215. return;
  1216. }
  1217. basic_fbstring(cbegin(), cend()).swap(*this);
  1218. }
  1219. void clear() {
  1220. resize(0);
  1221. }
  1222. bool empty() const {
  1223. return size() == 0;
  1224. }
  1225. // C++11 21.4.5 element access:
  1226. const_reference operator[](size_type pos) const {
  1227. return *(begin() + pos);
  1228. }
  1229. reference operator[](size_type pos) {
  1230. return *(begin() + pos);
  1231. }
  1232. const_reference at(size_type n) const {
  1233. enforce<std::out_of_range>(n < size(), "");
  1234. return (*this)[n];
  1235. }
  1236. reference at(size_type n) {
  1237. enforce<std::out_of_range>(n < size(), "");
  1238. return (*this)[n];
  1239. }
  1240. // C++11 21.4.6 modifiers:
  1241. basic_fbstring& operator+=(const basic_fbstring& str) {
  1242. return append(str);
  1243. }
  1244. basic_fbstring& operator+=(const value_type* s) {
  1245. return append(s);
  1246. }
  1247. basic_fbstring& operator+=(const value_type c) {
  1248. push_back(c);
  1249. return *this;
  1250. }
  1251. basic_fbstring& operator+=(std::initializer_list<value_type> il) {
  1252. append(il);
  1253. return *this;
  1254. }
  1255. basic_fbstring& append(const basic_fbstring& str);
  1256. basic_fbstring&
  1257. append(const basic_fbstring& str, const size_type pos, size_type n);
  1258. basic_fbstring& append(const value_type* s, size_type n);
  1259. basic_fbstring& append(const value_type* s) {
  1260. return append(s, traitsLength(s));
  1261. }
  1262. basic_fbstring& append(size_type n, value_type c);
  1263. template <class InputIterator>
  1264. basic_fbstring& append(InputIterator first, InputIterator last) {
  1265. insert(end(), first, last);
  1266. return *this;
  1267. }
  1268. basic_fbstring& append(std::initializer_list<value_type> il) {
  1269. return append(il.begin(), il.end());
  1270. }
  1271. void push_back(const value_type c) { // primitive
  1272. store_.push_back(c);
  1273. }
  1274. basic_fbstring& assign(const basic_fbstring& str) {
  1275. if (&str == this) {
  1276. return *this;
  1277. }
  1278. return assign(str.data(), str.size());
  1279. }
  1280. basic_fbstring& assign(basic_fbstring&& str) {
  1281. return *this = std::move(str);
  1282. }
  1283. basic_fbstring&
  1284. assign(const basic_fbstring& str, const size_type pos, size_type n);
  1285. basic_fbstring& assign(const value_type* s, const size_type n);
  1286. basic_fbstring& assign(const value_type* s) {
  1287. return assign(s, traitsLength(s));
  1288. }
  1289. basic_fbstring& assign(std::initializer_list<value_type> il) {
  1290. return assign(il.begin(), il.end());
  1291. }
  1292. template <class ItOrLength, class ItOrChar>
  1293. basic_fbstring& assign(ItOrLength first_or_n, ItOrChar last_or_c) {
  1294. return replace(begin(), end(), first_or_n, last_or_c);
  1295. }
  1296. basic_fbstring& insert(size_type pos1, const basic_fbstring& str) {
  1297. return insert(pos1, str.data(), str.size());
  1298. }
  1299. basic_fbstring& insert(
  1300. size_type pos1,
  1301. const basic_fbstring& str,
  1302. size_type pos2,
  1303. size_type n) {
  1304. enforce<std::out_of_range>(pos2 <= str.length(), "");
  1305. procrustes(n, str.length() - pos2);
  1306. return insert(pos1, str.data() + pos2, n);
  1307. }
  1308. basic_fbstring& insert(size_type pos, const value_type* s, size_type n) {
  1309. enforce<std::out_of_range>(pos <= length(), "");
  1310. insert(begin() + pos, s, s + n);
  1311. return *this;
  1312. }
  1313. basic_fbstring& insert(size_type pos, const value_type* s) {
  1314. return insert(pos, s, traitsLength(s));
  1315. }
  1316. basic_fbstring& insert(size_type pos, size_type n, value_type c) {
  1317. enforce<std::out_of_range>(pos <= length(), "");
  1318. insert(begin() + pos, n, c);
  1319. return *this;
  1320. }
  1321. iterator insert(const_iterator p, const value_type c) {
  1322. const size_type pos = p - cbegin();
  1323. insert(p, 1, c);
  1324. return begin() + pos;
  1325. }
  1326. #ifndef _LIBSTDCXX_FBSTRING
  1327. private:
  1328. typedef std::basic_istream<value_type, traits_type> istream_type;
  1329. istream_type& getlineImpl(istream_type& is, value_type delim);
  1330. public:
  1331. friend inline istream_type&
  1332. getline(istream_type& is, basic_fbstring& str, value_type delim) {
  1333. return str.getlineImpl(is, delim);
  1334. }
  1335. friend inline istream_type& getline(istream_type& is, basic_fbstring& str) {
  1336. return getline(is, str, '\n');
  1337. }
  1338. #endif
  1339. private:
  1340. iterator
  1341. insertImplDiscr(const_iterator i, size_type n, value_type c, std::true_type);
  1342. template <class InputIter>
  1343. iterator
  1344. insertImplDiscr(const_iterator i, InputIter b, InputIter e, std::false_type);
  1345. template <class FwdIterator>
  1346. iterator insertImpl(
  1347. const_iterator i,
  1348. FwdIterator s1,
  1349. FwdIterator s2,
  1350. std::forward_iterator_tag);
  1351. template <class InputIterator>
  1352. iterator insertImpl(
  1353. const_iterator i,
  1354. InputIterator b,
  1355. InputIterator e,
  1356. std::input_iterator_tag);
  1357. public:
  1358. template <class ItOrLength, class ItOrChar>
  1359. iterator insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c) {
  1360. using Sel = bool_constant<std::numeric_limits<ItOrLength>::is_specialized>;
  1361. return insertImplDiscr(p, first_or_n, last_or_c, Sel());
  1362. }
  1363. iterator insert(const_iterator p, std::initializer_list<value_type> il) {
  1364. return insert(p, il.begin(), il.end());
  1365. }
  1366. basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
  1367. Invariant checker(*this);
  1368. enforce<std::out_of_range>(pos <= length(), "");
  1369. procrustes(n, length() - pos);
  1370. std::copy(begin() + pos + n, end(), begin() + pos);
  1371. resize(length() - n);
  1372. return *this;
  1373. }
  1374. iterator erase(iterator position) {
  1375. const size_type pos(position - begin());
  1376. enforce<std::out_of_range>(pos <= size(), "");
  1377. erase(pos, 1);
  1378. return begin() + pos;
  1379. }
  1380. iterator erase(iterator first, iterator last) {
  1381. const size_type pos(first - begin());
  1382. erase(pos, last - first);
  1383. return begin() + pos;
  1384. }
  1385. // Replaces at most n1 chars of *this, starting with pos1 with the
  1386. // content of str
  1387. basic_fbstring&
  1388. replace(size_type pos1, size_type n1, const basic_fbstring& str) {
  1389. return replace(pos1, n1, str.data(), str.size());
  1390. }
  1391. // Replaces at most n1 chars of *this, starting with pos1,
  1392. // with at most n2 chars of str starting with pos2
  1393. basic_fbstring& replace(
  1394. size_type pos1,
  1395. size_type n1,
  1396. const basic_fbstring& str,
  1397. size_type pos2,
  1398. size_type n2) {
  1399. enforce<std::out_of_range>(pos2 <= str.length(), "");
  1400. return replace(
  1401. pos1, n1, str.data() + pos2, std::min(n2, str.size() - pos2));
  1402. }
  1403. // Replaces at most n1 chars of *this, starting with pos, with chars from s
  1404. basic_fbstring& replace(size_type pos, size_type n1, const value_type* s) {
  1405. return replace(pos, n1, s, traitsLength(s));
  1406. }
  1407. // Replaces at most n1 chars of *this, starting with pos, with n2
  1408. // occurrences of c
  1409. //
  1410. // consolidated with
  1411. //
  1412. // Replaces at most n1 chars of *this, starting with pos, with at
  1413. // most n2 chars of str. str must have at least n2 chars.
  1414. template <class StrOrLength, class NumOrChar>
  1415. basic_fbstring&
  1416. replace(size_type pos, size_type n1, StrOrLength s_or_n2, NumOrChar n_or_c) {
  1417. Invariant checker(*this);
  1418. enforce<std::out_of_range>(pos <= size(), "");
  1419. procrustes(n1, length() - pos);
  1420. const iterator b = begin() + pos;
  1421. return replace(b, b + n1, s_or_n2, n_or_c);
  1422. }
  1423. basic_fbstring& replace(iterator i1, iterator i2, const basic_fbstring& str) {
  1424. return replace(i1, i2, str.data(), str.length());
  1425. }
  1426. basic_fbstring& replace(iterator i1, iterator i2, const value_type* s) {
  1427. return replace(i1, i2, s, traitsLength(s));
  1428. }
  1429. private:
  1430. basic_fbstring& replaceImplDiscr(
  1431. iterator i1,
  1432. iterator i2,
  1433. const value_type* s,
  1434. size_type n,
  1435. std::integral_constant<int, 2>);
  1436. basic_fbstring& replaceImplDiscr(
  1437. iterator i1,
  1438. iterator i2,
  1439. size_type n2,
  1440. value_type c,
  1441. std::integral_constant<int, 1>);
  1442. template <class InputIter>
  1443. basic_fbstring& replaceImplDiscr(
  1444. iterator i1,
  1445. iterator i2,
  1446. InputIter b,
  1447. InputIter e,
  1448. std::integral_constant<int, 0>);
  1449. private:
  1450. template <class FwdIterator>
  1451. bool replaceAliased(
  1452. iterator /* i1 */,
  1453. iterator /* i2 */,
  1454. FwdIterator /* s1 */,
  1455. FwdIterator /* s2 */,
  1456. std::false_type) {
  1457. return false;
  1458. }
  1459. template <class FwdIterator>
  1460. bool replaceAliased(
  1461. iterator i1,
  1462. iterator i2,
  1463. FwdIterator s1,
  1464. FwdIterator s2,
  1465. std::true_type);
  1466. template <class FwdIterator>
  1467. void replaceImpl(
  1468. iterator i1,
  1469. iterator i2,
  1470. FwdIterator s1,
  1471. FwdIterator s2,
  1472. std::forward_iterator_tag);
  1473. template <class InputIterator>
  1474. void replaceImpl(
  1475. iterator i1,
  1476. iterator i2,
  1477. InputIterator b,
  1478. InputIterator e,
  1479. std::input_iterator_tag);
  1480. public:
  1481. template <class T1, class T2>
  1482. basic_fbstring&
  1483. replace(iterator i1, iterator i2, T1 first_or_n_or_s, T2 last_or_c_or_n) {
  1484. constexpr bool num1 = std::numeric_limits<T1>::is_specialized,
  1485. num2 = std::numeric_limits<T2>::is_specialized;
  1486. using Sel =
  1487. std::integral_constant<int, num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>;
  1488. return replaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n, Sel());
  1489. }
  1490. size_type copy(value_type* s, size_type n, size_type pos = 0) const {
  1491. enforce<std::out_of_range>(pos <= size(), "");
  1492. procrustes(n, size() - pos);
  1493. if (n != 0) {
  1494. fbstring_detail::podCopy(data() + pos, data() + pos + n, s);
  1495. }
  1496. return n;
  1497. }
  1498. void swap(basic_fbstring& rhs) {
  1499. store_.swap(rhs.store_);
  1500. }
  1501. const value_type* c_str() const {
  1502. return store_.c_str();
  1503. }
  1504. const value_type* data() const {
  1505. return c_str();
  1506. }
  1507. allocator_type get_allocator() const {
  1508. return allocator_type();
  1509. }
  1510. size_type find(const basic_fbstring& str, size_type pos = 0) const {
  1511. return find(str.data(), pos, str.length());
  1512. }
  1513. size_type find(const value_type* needle, size_type pos, size_type nsize)
  1514. const;
  1515. size_type find(const value_type* s, size_type pos = 0) const {
  1516. return find(s, pos, traitsLength(s));
  1517. }
  1518. size_type find(value_type c, size_type pos = 0) const {
  1519. return find(&c, pos, 1);
  1520. }
  1521. size_type rfind(const basic_fbstring& str, size_type pos = npos) const {
  1522. return rfind(str.data(), pos, str.length());
  1523. }
  1524. size_type rfind(const value_type* s, size_type pos, size_type n) const;
  1525. size_type rfind(const value_type* s, size_type pos = npos) const {
  1526. return rfind(s, pos, traitsLength(s));
  1527. }
  1528. size_type rfind(value_type c, size_type pos = npos) const {
  1529. return rfind(&c, pos, 1);
  1530. }
  1531. size_type find_first_of(const basic_fbstring& str, size_type pos = 0) const {
  1532. return find_first_of(str.data(), pos, str.length());
  1533. }
  1534. size_type find_first_of(const value_type* s, size_type pos, size_type n)
  1535. const;
  1536. size_type find_first_of(const value_type* s, size_type pos = 0) const {
  1537. return find_first_of(s, pos, traitsLength(s));
  1538. }
  1539. size_type find_first_of(value_type c, size_type pos = 0) const {
  1540. return find_first_of(&c, pos, 1);
  1541. }
  1542. size_type find_last_of(const basic_fbstring& str, size_type pos = npos)
  1543. const {
  1544. return find_last_of(str.data(), pos, str.length());
  1545. }
  1546. size_type find_last_of(const value_type* s, size_type pos, size_type n) const;
  1547. size_type find_last_of(const value_type* s, size_type pos = npos) const {
  1548. return find_last_of(s, pos, traitsLength(s));
  1549. }
  1550. size_type find_last_of(value_type c, size_type pos = npos) const {
  1551. return find_last_of(&c, pos, 1);
  1552. }
  1553. size_type find_first_not_of(const basic_fbstring& str, size_type pos = 0)
  1554. const {
  1555. return find_first_not_of(str.data(), pos, str.size());
  1556. }
  1557. size_type find_first_not_of(const value_type* s, size_type pos, size_type n)
  1558. const;
  1559. size_type find_first_not_of(const value_type* s, size_type pos = 0) const {
  1560. return find_first_not_of(s, pos, traitsLength(s));
  1561. }
  1562. size_type find_first_not_of(value_type c, size_type pos = 0) const {
  1563. return find_first_not_of(&c, pos, 1);
  1564. }
  1565. size_type find_last_not_of(const basic_fbstring& str, size_type pos = npos)
  1566. const {
  1567. return find_last_not_of(str.data(), pos, str.length());
  1568. }
  1569. size_type find_last_not_of(const value_type* s, size_type pos, size_type n)
  1570. const;
  1571. size_type find_last_not_of(const value_type* s, size_type pos = npos) const {
  1572. return find_last_not_of(s, pos, traitsLength(s));
  1573. }
  1574. size_type find_last_not_of(value_type c, size_type pos = npos) const {
  1575. return find_last_not_of(&c, pos, 1);
  1576. }
  1577. basic_fbstring substr(size_type pos = 0, size_type n = npos) const& {
  1578. enforce<std::out_of_range>(pos <= size(), "");
  1579. return basic_fbstring(data() + pos, std::min(n, size() - pos));
  1580. }
  1581. basic_fbstring substr(size_type pos = 0, size_type n = npos) && {
  1582. enforce<std::out_of_range>(pos <= size(), "");
  1583. erase(0, pos);
  1584. if (n < size()) {
  1585. resize(n);
  1586. }
  1587. return std::move(*this);
  1588. }
  1589. int compare(const basic_fbstring& str) const {
  1590. // FIX due to Goncalo N M de Carvalho July 18, 2005
  1591. return compare(0, size(), str);
  1592. }
  1593. int compare(size_type pos1, size_type n1, const basic_fbstring& str) const {
  1594. return compare(pos1, n1, str.data(), str.size());
  1595. }
  1596. int compare(size_type pos1, size_type n1, const value_type* s) const {
  1597. return compare(pos1, n1, s, traitsLength(s));
  1598. }
  1599. int compare(size_type pos1, size_type n1, const value_type* s, size_type n2)
  1600. const {
  1601. enforce<std::out_of_range>(pos1 <= size(), "");
  1602. procrustes(n1, size() - pos1);
  1603. // The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks!
  1604. const int r = traits_type::compare(pos1 + data(), s, std::min(n1, n2));
  1605. return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
  1606. }
  1607. int compare(
  1608. size_type pos1,
  1609. size_type n1,
  1610. const basic_fbstring& str,
  1611. size_type pos2,
  1612. size_type n2) const {
  1613. enforce<std::out_of_range>(pos2 <= str.size(), "");
  1614. return compare(
  1615. pos1, n1, str.data() + pos2, std::min(n2, str.size() - pos2));
  1616. }
  1617. // Code from Jean-Francois Bastien (03/26/2007)
  1618. int compare(const value_type* s) const {
  1619. // Could forward to compare(0, size(), s, traitsLength(s))
  1620. // but that does two extra checks
  1621. const size_type n1(size()), n2(traitsLength(s));
  1622. const int r = traits_type::compare(data(), s, std::min(n1, n2));
  1623. return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
  1624. }
  1625. private:
  1626. // Data
  1627. Storage store_;
  1628. };
  1629. template <typename E, class T, class A, class S>
  1630. FOLLY_MALLOC_NOINLINE inline typename basic_fbstring<E, T, A, S>::size_type
  1631. basic_fbstring<E, T, A, S>::traitsLength(const value_type* s) {
  1632. return s ? traits_type::length(s)
  1633. : (throw_exception<std::logic_error>(
  1634. "basic_fbstring: null pointer initializer not valid"),
  1635. 0);
  1636. }
  1637. template <typename E, class T, class A, class S>
  1638. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=(
  1639. const basic_fbstring& lhs) {
  1640. Invariant checker(*this);
  1641. if (FBSTRING_UNLIKELY(&lhs == this)) {
  1642. return *this;
  1643. }
  1644. return assign(lhs.data(), lhs.size());
  1645. }
  1646. // Move assignment
  1647. template <typename E, class T, class A, class S>
  1648. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=(
  1649. basic_fbstring&& goner) noexcept {
  1650. if (FBSTRING_UNLIKELY(&goner == this)) {
  1651. // Compatibility with std::basic_string<>,
  1652. // C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support.
  1653. return *this;
  1654. }
  1655. // No need of this anymore
  1656. this->~basic_fbstring();
  1657. // Move the goner into this
  1658. new (&store_) S(std::move(goner.store_));
  1659. return *this;
  1660. }
  1661. template <typename E, class T, class A, class S>
  1662. template <typename TP>
  1663. inline typename std::enable_if<
  1664. std::is_same<
  1665. typename std::decay<TP>::type,
  1666. typename folly::basic_fbstring<E, T, A, S>::value_type>::value,
  1667. basic_fbstring<E, T, A, S>&>::type
  1668. basic_fbstring<E, T, A, S>::operator=(TP c) {
  1669. Invariant checker(*this);
  1670. if (empty()) {
  1671. store_.expandNoinit(1);
  1672. } else if (store_.isShared()) {
  1673. basic_fbstring(1, c).swap(*this);
  1674. return *this;
  1675. } else {
  1676. store_.shrink(size() - 1);
  1677. }
  1678. front() = c;
  1679. return *this;
  1680. }
  1681. template <typename E, class T, class A, class S>
  1682. inline void basic_fbstring<E, T, A, S>::resize(
  1683. const size_type n,
  1684. const value_type c /*= value_type()*/) {
  1685. Invariant checker(*this);
  1686. auto size = this->size();
  1687. if (n <= size) {
  1688. store_.shrink(size - n);
  1689. } else {
  1690. auto const delta = n - size;
  1691. auto pData = store_.expandNoinit(delta);
  1692. fbstring_detail::podFill(pData, pData + delta, c);
  1693. }
  1694. FBSTRING_ASSERT(this->size() == n);
  1695. }
  1696. template <typename E, class T, class A, class S>
  1697. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(
  1698. const basic_fbstring& str) {
  1699. #ifndef NDEBUG
  1700. auto desiredSize = size() + str.size();
  1701. #endif
  1702. append(str.data(), str.size());
  1703. FBSTRING_ASSERT(size() == desiredSize);
  1704. return *this;
  1705. }
  1706. template <typename E, class T, class A, class S>
  1707. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(
  1708. const basic_fbstring& str,
  1709. const size_type pos,
  1710. size_type n) {
  1711. const size_type sz = str.size();
  1712. enforce<std::out_of_range>(pos <= sz, "");
  1713. procrustes(n, sz - pos);
  1714. return append(str.data() + pos, n);
  1715. }
  1716. template <typename E, class T, class A, class S>
  1717. FOLLY_MALLOC_NOINLINE inline basic_fbstring<E, T, A, S>&
  1718. basic_fbstring<E, T, A, S>::append(const value_type* s, size_type n) {
  1719. Invariant checker(*this);
  1720. if (FBSTRING_UNLIKELY(!n)) {
  1721. // Unlikely but must be done
  1722. return *this;
  1723. }
  1724. auto const oldSize = size();
  1725. auto const oldData = data();
  1726. auto pData = store_.expandNoinit(n, /* expGrowth = */ true);
  1727. // Check for aliasing (rare). We could use "<=" here but in theory
  1728. // those do not work for pointers unless the pointers point to
  1729. // elements in the same array. For that reason we use
  1730. // std::less_equal, which is guaranteed to offer a total order
  1731. // over pointers. See discussion at http://goo.gl/Cy2ya for more
  1732. // info.
  1733. std::less_equal<const value_type*> le;
  1734. if (FBSTRING_UNLIKELY(le(oldData, s) && !le(oldData + oldSize, s))) {
  1735. FBSTRING_ASSERT(le(s + n, oldData + oldSize));
  1736. // expandNoinit() could have moved the storage, restore the source.
  1737. s = data() + (s - oldData);
  1738. fbstring_detail::podMove(s, s + n, pData);
  1739. } else {
  1740. fbstring_detail::podCopy(s, s + n, pData);
  1741. }
  1742. FBSTRING_ASSERT(size() == oldSize + n);
  1743. return *this;
  1744. }
  1745. template <typename E, class T, class A, class S>
  1746. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(
  1747. size_type n,
  1748. value_type c) {
  1749. Invariant checker(*this);
  1750. auto pData = store_.expandNoinit(n, /* expGrowth = */ true);
  1751. fbstring_detail::podFill(pData, pData + n, c);
  1752. return *this;
  1753. }
  1754. template <typename E, class T, class A, class S>
  1755. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::assign(
  1756. const basic_fbstring& str,
  1757. const size_type pos,
  1758. size_type n) {
  1759. const size_type sz = str.size();
  1760. enforce<std::out_of_range>(pos <= sz, "");
  1761. procrustes(n, sz - pos);
  1762. return assign(str.data() + pos, n);
  1763. }
  1764. template <typename E, class T, class A, class S>
  1765. FOLLY_MALLOC_NOINLINE inline basic_fbstring<E, T, A, S>&
  1766. basic_fbstring<E, T, A, S>::assign(const value_type* s, const size_type n) {
  1767. Invariant checker(*this);
  1768. if (n == 0) {
  1769. resize(0);
  1770. } else if (size() >= n) {
  1771. // s can alias this, we need to use podMove.
  1772. fbstring_detail::podMove(s, s + n, store_.mutableData());
  1773. store_.shrink(size() - n);
  1774. FBSTRING_ASSERT(size() == n);
  1775. } else {
  1776. // If n is larger than size(), s cannot alias this string's
  1777. // storage.
  1778. resize(0);
  1779. // Do not use exponential growth here: assign() should be tight,
  1780. // to mirror the behavior of the equivalent constructor.
  1781. fbstring_detail::podCopy(s, s + n, store_.expandNoinit(n));
  1782. }
  1783. FBSTRING_ASSERT(size() == n);
  1784. return *this;
  1785. }
  1786. #ifndef _LIBSTDCXX_FBSTRING
  1787. template <typename E, class T, class A, class S>
  1788. inline typename basic_fbstring<E, T, A, S>::istream_type&
  1789. basic_fbstring<E, T, A, S>::getlineImpl(istream_type& is, value_type delim) {
  1790. Invariant checker(*this);
  1791. clear();
  1792. size_t size = 0;
  1793. while (true) {
  1794. size_t avail = capacity() - size;
  1795. // fbstring has 1 byte extra capacity for the null terminator,
  1796. // and getline null-terminates the read string.
  1797. is.getline(store_.expandNoinit(avail), avail + 1, delim);
  1798. size += is.gcount();
  1799. if (is.bad() || is.eof() || !is.fail()) {
  1800. // Done by either failure, end of file, or normal read.
  1801. if (!is.bad() && !is.eof()) {
  1802. --size; // gcount() also accounts for the delimiter.
  1803. }
  1804. resize(size);
  1805. break;
  1806. }
  1807. FBSTRING_ASSERT(size == this->size());
  1808. FBSTRING_ASSERT(size == capacity());
  1809. // Start at minimum allocation 63 + terminator = 64.
  1810. reserve(std::max<size_t>(63, 3 * size / 2));
  1811. // Clear the error so we can continue reading.
  1812. is.clear();
  1813. }
  1814. return is;
  1815. }
  1816. #endif
  1817. template <typename E, class T, class A, class S>
  1818. inline typename basic_fbstring<E, T, A, S>::size_type
  1819. basic_fbstring<E, T, A, S>::find(
  1820. const value_type* needle,
  1821. const size_type pos,
  1822. const size_type nsize) const {
  1823. auto const size = this->size();
  1824. // nsize + pos can overflow (eg pos == npos), guard against that by checking
  1825. // that nsize + pos does not wrap around.
  1826. if (nsize + pos > size || nsize + pos < pos) {
  1827. return npos;
  1828. }
  1829. if (nsize == 0) {
  1830. return pos;
  1831. }
  1832. // Don't use std::search, use a Boyer-Moore-like trick by comparing
  1833. // the last characters first
  1834. auto const haystack = data();
  1835. auto const nsize_1 = nsize - 1;
  1836. auto const lastNeedle = needle[nsize_1];
  1837. // Boyer-Moore skip value for the last char in the needle. Zero is
  1838. // not a valid value; skip will be computed the first time it's
  1839. // needed.
  1840. size_type skip = 0;
  1841. const E* i = haystack + pos;
  1842. auto iEnd = haystack + size - nsize_1;
  1843. while (i < iEnd) {
  1844. // Boyer-Moore: match the last element in the needle
  1845. while (i[nsize_1] != lastNeedle) {
  1846. if (++i == iEnd) {
  1847. // not found
  1848. return npos;
  1849. }
  1850. }
  1851. // Here we know that the last char matches
  1852. // Continue in pedestrian mode
  1853. for (size_t j = 0;;) {
  1854. FBSTRING_ASSERT(j < nsize);
  1855. if (i[j] != needle[j]) {
  1856. // Not found, we can skip
  1857. // Compute the skip value lazily
  1858. if (skip == 0) {
  1859. skip = 1;
  1860. while (skip <= nsize_1 && needle[nsize_1 - skip] != lastNeedle) {
  1861. ++skip;
  1862. }
  1863. }
  1864. i += skip;
  1865. break;
  1866. }
  1867. // Check if done searching
  1868. if (++j == nsize) {
  1869. // Yay
  1870. return i - haystack;
  1871. }
  1872. }
  1873. }
  1874. return npos;
  1875. }
  1876. template <typename E, class T, class A, class S>
  1877. inline typename basic_fbstring<E, T, A, S>::iterator
  1878. basic_fbstring<E, T, A, S>::insertImplDiscr(
  1879. const_iterator i,
  1880. size_type n,
  1881. value_type c,
  1882. std::true_type) {
  1883. Invariant checker(*this);
  1884. FBSTRING_ASSERT(i >= cbegin() && i <= cend());
  1885. const size_type pos = i - cbegin();
  1886. auto oldSize = size();
  1887. store_.expandNoinit(n, /* expGrowth = */ true);
  1888. auto b = begin();
  1889. fbstring_detail::podMove(b + pos, b + oldSize, b + pos + n);
  1890. fbstring_detail::podFill(b + pos, b + pos + n, c);
  1891. return b + pos;
  1892. }
  1893. template <typename E, class T, class A, class S>
  1894. template <class InputIter>
  1895. inline typename basic_fbstring<E, T, A, S>::iterator
  1896. basic_fbstring<E, T, A, S>::insertImplDiscr(
  1897. const_iterator i,
  1898. InputIter b,
  1899. InputIter e,
  1900. std::false_type) {
  1901. return insertImpl(
  1902. i, b, e, typename std::iterator_traits<InputIter>::iterator_category());
  1903. }
  1904. template <typename E, class T, class A, class S>
  1905. template <class FwdIterator>
  1906. inline typename basic_fbstring<E, T, A, S>::iterator
  1907. basic_fbstring<E, T, A, S>::insertImpl(
  1908. const_iterator i,
  1909. FwdIterator s1,
  1910. FwdIterator s2,
  1911. std::forward_iterator_tag) {
  1912. Invariant checker(*this);
  1913. FBSTRING_ASSERT(i >= cbegin() && i <= cend());
  1914. const size_type pos = i - cbegin();
  1915. auto n = std::distance(s1, s2);
  1916. FBSTRING_ASSERT(n >= 0);
  1917. auto oldSize = size();
  1918. store_.expandNoinit(n, /* expGrowth = */ true);
  1919. auto b = begin();
  1920. fbstring_detail::podMove(b + pos, b + oldSize, b + pos + n);
  1921. std::copy(s1, s2, b + pos);
  1922. return b + pos;
  1923. }
  1924. template <typename E, class T, class A, class S>
  1925. template <class InputIterator>
  1926. inline typename basic_fbstring<E, T, A, S>::iterator
  1927. basic_fbstring<E, T, A, S>::insertImpl(
  1928. const_iterator i,
  1929. InputIterator b,
  1930. InputIterator e,
  1931. std::input_iterator_tag) {
  1932. const auto pos = i - cbegin();
  1933. basic_fbstring temp(cbegin(), i);
  1934. for (; b != e; ++b) {
  1935. temp.push_back(*b);
  1936. }
  1937. temp.append(i, cend());
  1938. swap(temp);
  1939. return begin() + pos;
  1940. }
  1941. template <typename E, class T, class A, class S>
  1942. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr(
  1943. iterator i1,
  1944. iterator i2,
  1945. const value_type* s,
  1946. size_type n,
  1947. std::integral_constant<int, 2>) {
  1948. FBSTRING_ASSERT(i1 <= i2);
  1949. FBSTRING_ASSERT(begin() <= i1 && i1 <= end());
  1950. FBSTRING_ASSERT(begin() <= i2 && i2 <= end());
  1951. return replace(i1, i2, s, s + n);
  1952. }
  1953. template <typename E, class T, class A, class S>
  1954. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr(
  1955. iterator i1,
  1956. iterator i2,
  1957. size_type n2,
  1958. value_type c,
  1959. std::integral_constant<int, 1>) {
  1960. const size_type n1 = i2 - i1;
  1961. if (n1 > n2) {
  1962. std::fill(i1, i1 + n2, c);
  1963. erase(i1 + n2, i2);
  1964. } else {
  1965. std::fill(i1, i2, c);
  1966. insert(i2, n2 - n1, c);
  1967. }
  1968. FBSTRING_ASSERT(isSane());
  1969. return *this;
  1970. }
  1971. template <typename E, class T, class A, class S>
  1972. template <class InputIter>
  1973. inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr(
  1974. iterator i1,
  1975. iterator i2,
  1976. InputIter b,
  1977. InputIter e,
  1978. std::integral_constant<int, 0>) {
  1979. using Cat = typename std::iterator_traits<InputIter>::iterator_category;
  1980. replaceImpl(i1, i2, b, e, Cat());
  1981. return *this;
  1982. }
  1983. template <typename E, class T, class A, class S>
  1984. template <class FwdIterator>
  1985. inline bool basic_fbstring<E, T, A, S>::replaceAliased(
  1986. iterator i1,
  1987. iterator i2,
  1988. FwdIterator s1,
  1989. FwdIterator s2,
  1990. std::true_type) {
  1991. std::less_equal<const value_type*> le{};
  1992. const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
  1993. if (!aliased) {
  1994. return false;
  1995. }
  1996. // Aliased replace, copy to new string
  1997. basic_fbstring temp;
  1998. temp.reserve(size() - (i2 - i1) + std::distance(s1, s2));
  1999. temp.append(begin(), i1).append(s1, s2).append(i2, end());
  2000. swap(temp);
  2001. return true;
  2002. }
  2003. template <typename E, class T, class A, class S>
  2004. template <class FwdIterator>
  2005. inline void basic_fbstring<E, T, A, S>::replaceImpl(
  2006. iterator i1,
  2007. iterator i2,
  2008. FwdIterator s1,
  2009. FwdIterator s2,
  2010. std::forward_iterator_tag) {
  2011. Invariant checker(*this);
  2012. // Handle aliased replace
  2013. using Sel = bool_constant<
  2014. std::is_same<FwdIterator, iterator>::value ||
  2015. std::is_same<FwdIterator, const_iterator>::value>;
  2016. if (replaceAliased(i1, i2, s1, s2, Sel())) {
  2017. return;
  2018. }
  2019. auto const n1 = i2 - i1;
  2020. FBSTRING_ASSERT(n1 >= 0);
  2021. auto const n2 = std::distance(s1, s2);
  2022. FBSTRING_ASSERT(n2 >= 0);
  2023. if (n1 > n2) {
  2024. // shrinks
  2025. std::copy(s1, s2, i1);
  2026. erase(i1 + n2, i2);
  2027. } else {
  2028. // grows
  2029. s1 = fbstring_detail::copy_n(s1, n1, i1).first;
  2030. insert(i2, s1, s2);
  2031. }
  2032. FBSTRING_ASSERT(isSane());
  2033. }
  2034. template <typename E, class T, class A, class S>
  2035. template <class InputIterator>
  2036. inline void basic_fbstring<E, T, A, S>::replaceImpl(
  2037. iterator i1,
  2038. iterator i2,
  2039. InputIterator b,
  2040. InputIterator e,
  2041. std::input_iterator_tag) {
  2042. basic_fbstring temp(begin(), i1);
  2043. temp.append(b, e).append(i2, end());
  2044. swap(temp);
  2045. }
  2046. template <typename E, class T, class A, class S>
  2047. inline typename basic_fbstring<E, T, A, S>::size_type
  2048. basic_fbstring<E, T, A, S>::rfind(
  2049. const value_type* s,
  2050. size_type pos,
  2051. size_type n) const {
  2052. if (n > length()) {
  2053. return npos;
  2054. }
  2055. pos = std::min(pos, length() - n);
  2056. if (n == 0) {
  2057. return pos;
  2058. }
  2059. const_iterator i(begin() + pos);
  2060. for (;; --i) {
  2061. if (traits_type::eq(*i, *s) && traits_type::compare(&*i, s, n) == 0) {
  2062. return i - begin();
  2063. }
  2064. if (i == begin()) {
  2065. break;
  2066. }
  2067. }
  2068. return npos;
  2069. }
  2070. template <typename E, class T, class A, class S>
  2071. inline typename basic_fbstring<E, T, A, S>::size_type
  2072. basic_fbstring<E, T, A, S>::find_first_of(
  2073. const value_type* s,
  2074. size_type pos,
  2075. size_type n) const {
  2076. if (pos > length() || n == 0) {
  2077. return npos;
  2078. }
  2079. const_iterator i(begin() + pos), finish(end());
  2080. for (; i != finish; ++i) {
  2081. if (traits_type::find(s, n, *i) != nullptr) {
  2082. return i - begin();
  2083. }
  2084. }
  2085. return npos;
  2086. }
  2087. template <typename E, class T, class A, class S>
  2088. inline typename basic_fbstring<E, T, A, S>::size_type
  2089. basic_fbstring<E, T, A, S>::find_last_of(
  2090. const value_type* s,
  2091. size_type pos,
  2092. size_type n) const {
  2093. if (!empty() && n > 0) {
  2094. pos = std::min(pos, length() - 1);
  2095. const_iterator i(begin() + pos);
  2096. for (;; --i) {
  2097. if (traits_type::find(s, n, *i) != nullptr) {
  2098. return i - begin();
  2099. }
  2100. if (i == begin()) {
  2101. break;
  2102. }
  2103. }
  2104. }
  2105. return npos;
  2106. }
  2107. template <typename E, class T, class A, class S>
  2108. inline typename basic_fbstring<E, T, A, S>::size_type
  2109. basic_fbstring<E, T, A, S>::find_first_not_of(
  2110. const value_type* s,
  2111. size_type pos,
  2112. size_type n) const {
  2113. if (pos < length()) {
  2114. const_iterator i(begin() + pos), finish(end());
  2115. for (; i != finish; ++i) {
  2116. if (traits_type::find(s, n, *i) == nullptr) {
  2117. return i - begin();
  2118. }
  2119. }
  2120. }
  2121. return npos;
  2122. }
  2123. template <typename E, class T, class A, class S>
  2124. inline typename basic_fbstring<E, T, A, S>::size_type
  2125. basic_fbstring<E, T, A, S>::find_last_not_of(
  2126. const value_type* s,
  2127. size_type pos,
  2128. size_type n) const {
  2129. if (!this->empty()) {
  2130. pos = std::min(pos, size() - 1);
  2131. const_iterator i(begin() + pos);
  2132. for (;; --i) {
  2133. if (traits_type::find(s, n, *i) == nullptr) {
  2134. return i - begin();
  2135. }
  2136. if (i == begin()) {
  2137. break;
  2138. }
  2139. }
  2140. }
  2141. return npos;
  2142. }
  2143. // non-member functions
  2144. // C++11 21.4.8.1/1
  2145. template <typename E, class T, class A, class S>
  2146. inline basic_fbstring<E, T, A, S> operator+(
  2147. const basic_fbstring<E, T, A, S>& lhs,
  2148. const basic_fbstring<E, T, A, S>& rhs) {
  2149. basic_fbstring<E, T, A, S> result;
  2150. result.reserve(lhs.size() + rhs.size());
  2151. result.append(lhs).append(rhs);
  2152. return std::move(result);
  2153. }
  2154. // C++11 21.4.8.1/2
  2155. template <typename E, class T, class A, class S>
  2156. inline basic_fbstring<E, T, A, S> operator+(
  2157. basic_fbstring<E, T, A, S>&& lhs,
  2158. const basic_fbstring<E, T, A, S>& rhs) {
  2159. return std::move(lhs.append(rhs));
  2160. }
  2161. // C++11 21.4.8.1/3
  2162. template <typename E, class T, class A, class S>
  2163. inline basic_fbstring<E, T, A, S> operator+(
  2164. const basic_fbstring<E, T, A, S>& lhs,
  2165. basic_fbstring<E, T, A, S>&& rhs) {
  2166. if (rhs.capacity() >= lhs.size() + rhs.size()) {
  2167. // Good, at least we don't need to reallocate
  2168. return std::move(rhs.insert(0, lhs));
  2169. }
  2170. // Meh, no go. Forward to operator+(const&, const&).
  2171. auto const& rhsC = rhs;
  2172. return lhs + rhsC;
  2173. }
  2174. // C++11 21.4.8.1/4
  2175. template <typename E, class T, class A, class S>
  2176. inline basic_fbstring<E, T, A, S> operator+(
  2177. basic_fbstring<E, T, A, S>&& lhs,
  2178. basic_fbstring<E, T, A, S>&& rhs) {
  2179. return std::move(lhs.append(rhs));
  2180. }
  2181. // C++11 21.4.8.1/5
  2182. template <typename E, class T, class A, class S>
  2183. inline basic_fbstring<E, T, A, S> operator+(
  2184. const E* lhs,
  2185. const basic_fbstring<E, T, A, S>& rhs) {
  2186. //
  2187. basic_fbstring<E, T, A, S> result;
  2188. const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
  2189. result.reserve(len + rhs.size());
  2190. result.append(lhs, len).append(rhs);
  2191. return result;
  2192. }
  2193. // C++11 21.4.8.1/6
  2194. template <typename E, class T, class A, class S>
  2195. inline basic_fbstring<E, T, A, S> operator+(
  2196. const E* lhs,
  2197. basic_fbstring<E, T, A, S>&& rhs) {
  2198. //
  2199. const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
  2200. if (rhs.capacity() >= len + rhs.size()) {
  2201. // Good, at least we don't need to reallocate
  2202. rhs.insert(rhs.begin(), lhs, lhs + len);
  2203. return std::move(rhs);
  2204. }
  2205. // Meh, no go. Do it by hand since we have len already.
  2206. basic_fbstring<E, T, A, S> result;
  2207. result.reserve(len + rhs.size());
  2208. result.append(lhs, len).append(rhs);
  2209. return result;
  2210. }
  2211. // C++11 21.4.8.1/7
  2212. template <typename E, class T, class A, class S>
  2213. inline basic_fbstring<E, T, A, S> operator+(
  2214. E lhs,
  2215. const basic_fbstring<E, T, A, S>& rhs) {
  2216. basic_fbstring<E, T, A, S> result;
  2217. result.reserve(1 + rhs.size());
  2218. result.push_back(lhs);
  2219. result.append(rhs);
  2220. return result;
  2221. }
  2222. // C++11 21.4.8.1/8
  2223. template <typename E, class T, class A, class S>
  2224. inline basic_fbstring<E, T, A, S> operator+(
  2225. E lhs,
  2226. basic_fbstring<E, T, A, S>&& rhs) {
  2227. //
  2228. if (rhs.capacity() > rhs.size()) {
  2229. // Good, at least we don't need to reallocate
  2230. rhs.insert(rhs.begin(), lhs);
  2231. return std::move(rhs);
  2232. }
  2233. // Meh, no go. Forward to operator+(E, const&).
  2234. auto const& rhsC = rhs;
  2235. return lhs + rhsC;
  2236. }
  2237. // C++11 21.4.8.1/9
  2238. template <typename E, class T, class A, class S>
  2239. inline basic_fbstring<E, T, A, S> operator+(
  2240. const basic_fbstring<E, T, A, S>& lhs,
  2241. const E* rhs) {
  2242. typedef typename basic_fbstring<E, T, A, S>::size_type size_type;
  2243. typedef typename basic_fbstring<E, T, A, S>::traits_type traits_type;
  2244. basic_fbstring<E, T, A, S> result;
  2245. const size_type len = traits_type::length(rhs);
  2246. result.reserve(lhs.size() + len);
  2247. result.append(lhs).append(rhs, len);
  2248. return result;
  2249. }
  2250. // C++11 21.4.8.1/10
  2251. template <typename E, class T, class A, class S>
  2252. inline basic_fbstring<E, T, A, S> operator+(
  2253. basic_fbstring<E, T, A, S>&& lhs,
  2254. const E* rhs) {
  2255. //
  2256. return std::move(lhs += rhs);
  2257. }
  2258. // C++11 21.4.8.1/11
  2259. template <typename E, class T, class A, class S>
  2260. inline basic_fbstring<E, T, A, S> operator+(
  2261. const basic_fbstring<E, T, A, S>& lhs,
  2262. E rhs) {
  2263. basic_fbstring<E, T, A, S> result;
  2264. result.reserve(lhs.size() + 1);
  2265. result.append(lhs);
  2266. result.push_back(rhs);
  2267. return result;
  2268. }
  2269. // C++11 21.4.8.1/12
  2270. template <typename E, class T, class A, class S>
  2271. inline basic_fbstring<E, T, A, S> operator+(
  2272. basic_fbstring<E, T, A, S>&& lhs,
  2273. E rhs) {
  2274. //
  2275. return std::move(lhs += rhs);
  2276. }
  2277. template <typename E, class T, class A, class S>
  2278. inline bool operator==(
  2279. const basic_fbstring<E, T, A, S>& lhs,
  2280. const basic_fbstring<E, T, A, S>& rhs) {
  2281. return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
  2282. }
  2283. template <typename E, class T, class A, class S>
  2284. inline bool operator==(
  2285. const typename basic_fbstring<E, T, A, S>::value_type* lhs,
  2286. const basic_fbstring<E, T, A, S>& rhs) {
  2287. return rhs == lhs;
  2288. }
  2289. template <typename E, class T, class A, class S>
  2290. inline bool operator==(
  2291. const basic_fbstring<E, T, A, S>& lhs,
  2292. const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
  2293. return lhs.compare(rhs) == 0;
  2294. }
  2295. template <typename E, class T, class A, class S>
  2296. inline bool operator!=(
  2297. const basic_fbstring<E, T, A, S>& lhs,
  2298. const basic_fbstring<E, T, A, S>& rhs) {
  2299. return !(lhs == rhs);
  2300. }
  2301. template <typename E, class T, class A, class S>
  2302. inline bool operator!=(
  2303. const typename basic_fbstring<E, T, A, S>::value_type* lhs,
  2304. const basic_fbstring<E, T, A, S>& rhs) {
  2305. return !(lhs == rhs);
  2306. }
  2307. template <typename E, class T, class A, class S>
  2308. inline bool operator!=(
  2309. const basic_fbstring<E, T, A, S>& lhs,
  2310. const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
  2311. return !(lhs == rhs);
  2312. }
  2313. template <typename E, class T, class A, class S>
  2314. inline bool operator<(
  2315. const basic_fbstring<E, T, A, S>& lhs,
  2316. const basic_fbstring<E, T, A, S>& rhs) {
  2317. return lhs.compare(rhs) < 0;
  2318. }
  2319. template <typename E, class T, class A, class S>
  2320. inline bool operator<(
  2321. const basic_fbstring<E, T, A, S>& lhs,
  2322. const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
  2323. return lhs.compare(rhs) < 0;
  2324. }
  2325. template <typename E, class T, class A, class S>
  2326. inline bool operator<(
  2327. const typename basic_fbstring<E, T, A, S>::value_type* lhs,
  2328. const basic_fbstring<E, T, A, S>& rhs) {
  2329. return rhs.compare(lhs) > 0;
  2330. }
  2331. template <typename E, class T, class A, class S>
  2332. inline bool operator>(
  2333. const basic_fbstring<E, T, A, S>& lhs,
  2334. const basic_fbstring<E, T, A, S>& rhs) {
  2335. return rhs < lhs;
  2336. }
  2337. template <typename E, class T, class A, class S>
  2338. inline bool operator>(
  2339. const basic_fbstring<E, T, A, S>& lhs,
  2340. const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
  2341. return rhs < lhs;
  2342. }
  2343. template <typename E, class T, class A, class S>
  2344. inline bool operator>(
  2345. const typename basic_fbstring<E, T, A, S>::value_type* lhs,
  2346. const basic_fbstring<E, T, A, S>& rhs) {
  2347. return rhs < lhs;
  2348. }
  2349. template <typename E, class T, class A, class S>
  2350. inline bool operator<=(
  2351. const basic_fbstring<E, T, A, S>& lhs,
  2352. const basic_fbstring<E, T, A, S>& rhs) {
  2353. return !(rhs < lhs);
  2354. }
  2355. template <typename E, class T, class A, class S>
  2356. inline bool operator<=(
  2357. const basic_fbstring<E, T, A, S>& lhs,
  2358. const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
  2359. return !(rhs < lhs);
  2360. }
  2361. template <typename E, class T, class A, class S>
  2362. inline bool operator<=(
  2363. const typename basic_fbstring<E, T, A, S>::value_type* lhs,
  2364. const basic_fbstring<E, T, A, S>& rhs) {
  2365. return !(rhs < lhs);
  2366. }
  2367. template <typename E, class T, class A, class S>
  2368. inline bool operator>=(
  2369. const basic_fbstring<E, T, A, S>& lhs,
  2370. const basic_fbstring<E, T, A, S>& rhs) {
  2371. return !(lhs < rhs);
  2372. }
  2373. template <typename E, class T, class A, class S>
  2374. inline bool operator>=(
  2375. const basic_fbstring<E, T, A, S>& lhs,
  2376. const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
  2377. return !(lhs < rhs);
  2378. }
  2379. template <typename E, class T, class A, class S>
  2380. inline bool operator>=(
  2381. const typename basic_fbstring<E, T, A, S>::value_type* lhs,
  2382. const basic_fbstring<E, T, A, S>& rhs) {
  2383. return !(lhs < rhs);
  2384. }
  2385. // C++11 21.4.8.8
  2386. template <typename E, class T, class A, class S>
  2387. void swap(basic_fbstring<E, T, A, S>& lhs, basic_fbstring<E, T, A, S>& rhs) {
  2388. lhs.swap(rhs);
  2389. }
  2390. // TODO: make this faster.
  2391. template <typename E, class T, class A, class S>
  2392. inline std::basic_istream<
  2393. typename basic_fbstring<E, T, A, S>::value_type,
  2394. typename basic_fbstring<E, T, A, S>::traits_type>&
  2395. operator>>(
  2396. std::basic_istream<
  2397. typename basic_fbstring<E, T, A, S>::value_type,
  2398. typename basic_fbstring<E, T, A, S>::traits_type>& is,
  2399. basic_fbstring<E, T, A, S>& str) {
  2400. typedef std::basic_istream<
  2401. typename basic_fbstring<E, T, A, S>::value_type,
  2402. typename basic_fbstring<E, T, A, S>::traits_type>
  2403. _istream_type;
  2404. typename _istream_type::sentry sentry(is);
  2405. size_t extracted = 0;
  2406. auto err = _istream_type::goodbit;
  2407. if (sentry) {
  2408. auto n = is.width();
  2409. if (n <= 0) {
  2410. n = str.max_size();
  2411. }
  2412. str.erase();
  2413. for (auto got = is.rdbuf()->sgetc(); extracted != size_t(n); ++extracted) {
  2414. if (got == T::eof()) {
  2415. err |= _istream_type::eofbit;
  2416. is.width(0);
  2417. break;
  2418. }
  2419. if (isspace(got)) {
  2420. break;
  2421. }
  2422. str.push_back(got);
  2423. got = is.rdbuf()->snextc();
  2424. }
  2425. }
  2426. if (!extracted) {
  2427. err |= _istream_type::failbit;
  2428. }
  2429. if (err) {
  2430. is.setstate(err);
  2431. }
  2432. return is;
  2433. }
  2434. template <typename E, class T, class A, class S>
  2435. inline std::basic_ostream<
  2436. typename basic_fbstring<E, T, A, S>::value_type,
  2437. typename basic_fbstring<E, T, A, S>::traits_type>&
  2438. operator<<(
  2439. std::basic_ostream<
  2440. typename basic_fbstring<E, T, A, S>::value_type,
  2441. typename basic_fbstring<E, T, A, S>::traits_type>& os,
  2442. const basic_fbstring<E, T, A, S>& str) {
  2443. #if _LIBCPP_VERSION
  2444. typedef std::basic_ostream<
  2445. typename basic_fbstring<E, T, A, S>::value_type,
  2446. typename basic_fbstring<E, T, A, S>::traits_type>
  2447. _ostream_type;
  2448. typename _ostream_type::sentry _s(os);
  2449. if (_s) {
  2450. typedef std::ostreambuf_iterator<
  2451. typename basic_fbstring<E, T, A, S>::value_type,
  2452. typename basic_fbstring<E, T, A, S>::traits_type>
  2453. _Ip;
  2454. size_t __len = str.size();
  2455. bool __left =
  2456. (os.flags() & _ostream_type::adjustfield) == _ostream_type::left;
  2457. if (__pad_and_output(
  2458. _Ip(os),
  2459. str.data(),
  2460. __left ? str.data() + __len : str.data(),
  2461. str.data() + __len,
  2462. os,
  2463. os.fill())
  2464. .failed()) {
  2465. os.setstate(_ostream_type::badbit | _ostream_type::failbit);
  2466. }
  2467. }
  2468. #elif defined(_MSC_VER)
  2469. typedef decltype(os.precision()) streamsize;
  2470. // MSVC doesn't define __ostream_insert
  2471. os.write(str.data(), static_cast<streamsize>(str.size()));
  2472. #else
  2473. std::__ostream_insert(os, str.data(), str.size());
  2474. #endif
  2475. return os;
  2476. }
  2477. template <typename E1, class T, class A, class S>
  2478. constexpr typename basic_fbstring<E1, T, A, S>::size_type
  2479. basic_fbstring<E1, T, A, S>::npos;
  2480. #ifndef _LIBSTDCXX_FBSTRING
  2481. // basic_string compatibility routines
  2482. template <typename E, class T, class A, class S, class A2>
  2483. inline bool operator==(
  2484. const basic_fbstring<E, T, A, S>& lhs,
  2485. const std::basic_string<E, T, A2>& rhs) {
  2486. return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) == 0;
  2487. }
  2488. template <typename E, class T, class A, class S, class A2>
  2489. inline bool operator==(
  2490. const std::basic_string<E, T, A2>& lhs,
  2491. const basic_fbstring<E, T, A, S>& rhs) {
  2492. return rhs == lhs;
  2493. }
  2494. template <typename E, class T, class A, class S, class A2>
  2495. inline bool operator!=(
  2496. const basic_fbstring<E, T, A, S>& lhs,
  2497. const std::basic_string<E, T, A2>& rhs) {
  2498. return !(lhs == rhs);
  2499. }
  2500. template <typename E, class T, class A, class S, class A2>
  2501. inline bool operator!=(
  2502. const std::basic_string<E, T, A2>& lhs,
  2503. const basic_fbstring<E, T, A, S>& rhs) {
  2504. return !(lhs == rhs);
  2505. }
  2506. template <typename E, class T, class A, class S, class A2>
  2507. inline bool operator<(
  2508. const basic_fbstring<E, T, A, S>& lhs,
  2509. const std::basic_string<E, T, A2>& rhs) {
  2510. return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) < 0;
  2511. }
  2512. template <typename E, class T, class A, class S, class A2>
  2513. inline bool operator>(
  2514. const basic_fbstring<E, T, A, S>& lhs,
  2515. const std::basic_string<E, T, A2>& rhs) {
  2516. return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) > 0;
  2517. }
  2518. template <typename E, class T, class A, class S, class A2>
  2519. inline bool operator<(
  2520. const std::basic_string<E, T, A2>& lhs,
  2521. const basic_fbstring<E, T, A, S>& rhs) {
  2522. return rhs > lhs;
  2523. }
  2524. template <typename E, class T, class A, class S, class A2>
  2525. inline bool operator>(
  2526. const std::basic_string<E, T, A2>& lhs,
  2527. const basic_fbstring<E, T, A, S>& rhs) {
  2528. return rhs < lhs;
  2529. }
  2530. template <typename E, class T, class A, class S, class A2>
  2531. inline bool operator<=(
  2532. const basic_fbstring<E, T, A, S>& lhs,
  2533. const std::basic_string<E, T, A2>& rhs) {
  2534. return !(lhs > rhs);
  2535. }
  2536. template <typename E, class T, class A, class S, class A2>
  2537. inline bool operator>=(
  2538. const basic_fbstring<E, T, A, S>& lhs,
  2539. const std::basic_string<E, T, A2>& rhs) {
  2540. return !(lhs < rhs);
  2541. }
  2542. template <typename E, class T, class A, class S, class A2>
  2543. inline bool operator<=(
  2544. const std::basic_string<E, T, A2>& lhs,
  2545. const basic_fbstring<E, T, A, S>& rhs) {
  2546. return !(lhs > rhs);
  2547. }
  2548. template <typename E, class T, class A, class S, class A2>
  2549. inline bool operator>=(
  2550. const std::basic_string<E, T, A2>& lhs,
  2551. const basic_fbstring<E, T, A, S>& rhs) {
  2552. return !(lhs < rhs);
  2553. }
  2554. #if !defined(_LIBSTDCXX_FBSTRING)
  2555. typedef basic_fbstring<char> fbstring;
  2556. #endif
  2557. // fbstring is relocatable
  2558. template <class T, class R, class A, class S>
  2559. FOLLY_ASSUME_RELOCATABLE(basic_fbstring<T, R, A, S>);
  2560. #endif
  2561. FOLLY_FBSTRING_END_NAMESPACE
  2562. #ifndef _LIBSTDCXX_FBSTRING
  2563. // Hash functions to make fbstring usable with e.g. hash_map
  2564. //
  2565. // Handle interaction with different C++ standard libraries, which
  2566. // expect these types to be in different namespaces.
  2567. #define FOLLY_FBSTRING_HASH1(T) \
  2568. template <> \
  2569. struct hash<::folly::basic_fbstring<T>> { \
  2570. size_t operator()(const ::folly::basic_fbstring<T>& s) const { \
  2571. return ::folly::hash::fnv32_buf(s.data(), s.size() * sizeof(T)); \
  2572. } \
  2573. };
  2574. // The C++11 standard says that these four are defined
  2575. #define FOLLY_FBSTRING_HASH \
  2576. FOLLY_FBSTRING_HASH1(char) \
  2577. FOLLY_FBSTRING_HASH1(char16_t) \
  2578. FOLLY_FBSTRING_HASH1(char32_t) \
  2579. FOLLY_FBSTRING_HASH1(wchar_t)
  2580. namespace std {
  2581. FOLLY_FBSTRING_HASH
  2582. } // namespace std
  2583. #undef FOLLY_FBSTRING_HASH
  2584. #undef FOLLY_FBSTRING_HASH1
  2585. #endif // _LIBSTDCXX_FBSTRING
  2586. FOLLY_POP_WARNING
  2587. #undef FBSTRING_DISABLE_SSO
  2588. #undef FBSTRING_SANITIZE_ADDRESS
  2589. #undef throw
  2590. #undef FBSTRING_LIKELY
  2591. #undef FBSTRING_UNLIKELY
  2592. #undef FBSTRING_ASSERT
  2593. #ifndef _LIBSTDCXX_FBSTRING
  2594. namespace folly {
  2595. template <class T>
  2596. struct IsSomeString;
  2597. template <>
  2598. struct IsSomeString<fbstring> : std::true_type {};
  2599. } // namespace folly
  2600. #endif