123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641 |
- // Copyright 2018 The Abseil Authors.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // https://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "absl/container/internal/layout.h"
- // We need ::max_align_t because some libstdc++ versions don't provide
- // std::max_align_t
- #include <stddef.h>
- #include <cstdint>
- #include <memory>
- #include <sstream>
- #include <type_traits>
- #include "gmock/gmock.h"
- #include "gtest/gtest.h"
- #include "absl/base/config.h"
- #include "absl/base/internal/raw_logging.h"
- #include "absl/types/span.h"
- namespace absl {
- ABSL_NAMESPACE_BEGIN
- namespace container_internal {
- namespace {
- using ::absl::Span;
- using ::testing::ElementsAre;
- size_t Distance(const void* from, const void* to) {
- ABSL_RAW_CHECK(from <= to, "Distance must be non-negative");
- return static_cast<const char*>(to) - static_cast<const char*>(from);
- }
- template <class Expected, class Actual>
- Expected Type(Actual val) {
- static_assert(std::is_same<Expected, Actual>(), "");
- return val;
- }
- // Helper classes to test different size and alignments.
- struct alignas(8) Int128 {
- uint64_t a, b;
- friend bool operator==(Int128 lhs, Int128 rhs) {
- return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
- }
- static std::string Name() {
- return internal_layout::adl_barrier::TypeName<Int128>();
- }
- };
- // int64_t is *not* 8-byte aligned on all platforms!
- struct alignas(8) Int64 {
- int64_t a;
- friend bool operator==(Int64 lhs, Int64 rhs) {
- return lhs.a == rhs.a;
- }
- };
- // Properties of types that this test relies on.
- static_assert(sizeof(int8_t) == 1, "");
- static_assert(alignof(int8_t) == 1, "");
- static_assert(sizeof(int16_t) == 2, "");
- static_assert(alignof(int16_t) == 2, "");
- static_assert(sizeof(int32_t) == 4, "");
- static_assert(alignof(int32_t) == 4, "");
- static_assert(sizeof(Int64) == 8, "");
- static_assert(alignof(Int64) == 8, "");
- static_assert(sizeof(Int128) == 16, "");
- static_assert(alignof(Int128) == 8, "");
- template <class Expected, class Actual>
- void SameType() {
- static_assert(std::is_same<Expected, Actual>(), "");
- }
- TEST(Layout, ElementType) {
- {
- using L = Layout<int32_t>;
- SameType<int32_t, L::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
- }
- {
- using L = Layout<int32_t, int32_t>;
- SameType<int32_t, L::ElementType<0>>();
- SameType<int32_t, L::ElementType<1>>();
- SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial())::ElementType<1>>();
- SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- SameType<int8_t, L::ElementType<0>>();
- SameType<int32_t, L::ElementType<1>>();
- SameType<Int128, L::ElementType<2>>();
- SameType<int8_t, decltype(L::Partial())::ElementType<0>>();
- SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
- SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();
- SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();
- SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();
- SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();
- SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();
- }
- }
- TEST(Layout, ElementTypes) {
- {
- using L = Layout<int32_t>;
- SameType<std::tuple<int32_t>, L::ElementTypes>();
- SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();
- SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();
- }
- {
- using L = Layout<int32_t, int32_t>;
- SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
- SameType<std::tuple<int32_t, int32_t>,
- decltype(L::Partial())::ElementTypes>();
- SameType<std::tuple<int32_t, int32_t>,
- decltype(L::Partial(0))::ElementTypes>();
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();
- SameType<std::tuple<int8_t, int32_t, Int128>,
- decltype(L::Partial())::ElementTypes>();
- SameType<std::tuple<int8_t, int32_t, Int128>,
- decltype(L::Partial(0))::ElementTypes>();
- SameType<std::tuple<int8_t, int32_t, Int128>,
- decltype(L::Partial(0, 0))::ElementTypes>();
- SameType<std::tuple<int8_t, int32_t, Int128>,
- decltype(L::Partial(0, 0, 0))::ElementTypes>();
- }
- }
- TEST(Layout, OffsetByIndex) {
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial().Offset<0>());
- EXPECT_EQ(0, L::Partial(3).Offset<0>());
- EXPECT_EQ(0, L(3).Offset<0>());
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(0, L::Partial().Offset<0>());
- EXPECT_EQ(0, L::Partial(3).Offset<0>());
- EXPECT_EQ(12, L::Partial(3).Offset<1>());
- EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());
- EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());
- EXPECT_EQ(0, L(3, 5).Offset<0>());
- EXPECT_EQ(12, L(3, 5).Offset<1>());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, L::Partial().Offset<0>());
- EXPECT_EQ(0, L::Partial(0).Offset<0>());
- EXPECT_EQ(0, L::Partial(0).Offset<1>());
- EXPECT_EQ(0, L::Partial(1).Offset<0>());
- EXPECT_EQ(4, L::Partial(1).Offset<1>());
- EXPECT_EQ(0, L::Partial(5).Offset<0>());
- EXPECT_EQ(8, L::Partial(5).Offset<1>());
- EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());
- EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());
- EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());
- EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());
- EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());
- EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());
- EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());
- EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());
- EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());
- EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());
- EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());
- EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());
- EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());
- EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());
- EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());
- EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());
- EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());
- EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());
- EXPECT_EQ(0, L(5, 3, 1).Offset<0>());
- EXPECT_EQ(24, L(5, 3, 1).Offset<2>());
- EXPECT_EQ(8, L(5, 3, 1).Offset<1>());
- }
- }
- TEST(Layout, OffsetByType) {
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial().Offset<int32_t>());
- EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());
- EXPECT_EQ(0, L(3).Offset<int32_t>());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, L::Partial().Offset<int8_t>());
- EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());
- EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());
- EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());
- EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());
- EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());
- EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());
- EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());
- EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());
- EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());
- EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());
- EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());
- EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());
- EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());
- EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());
- EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());
- EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());
- EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());
- EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());
- EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());
- EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());
- EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());
- EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());
- EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());
- EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());
- EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());
- EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());
- EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());
- }
- }
- TEST(Layout, Offsets) {
- {
- using L = Layout<int32_t>;
- EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
- EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));
- EXPECT_THAT(L(3).Offsets(), ElementsAre(0));
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
- EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));
- EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));
- EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
- EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));
- EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));
- EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));
- EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));
- EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));
- EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));
- EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));
- EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
- EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
- }
- }
- TEST(Layout, AllocSize) {
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).AllocSize());
- EXPECT_EQ(12, L::Partial(3).AllocSize());
- EXPECT_EQ(12, L(3).AllocSize());
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(32, L::Partial(3, 5).AllocSize());
- EXPECT_EQ(32, L(3, 5).AllocSize());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());
- EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());
- EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());
- EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());
- EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());
- EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());
- EXPECT_EQ(136, L(3, 5, 7).AllocSize());
- }
- }
- TEST(Layout, SizeByIndex) {
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).Size<0>());
- EXPECT_EQ(3, L::Partial(3).Size<0>());
- EXPECT_EQ(3, L(3).Size<0>());
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(0, L::Partial(0).Size<0>());
- EXPECT_EQ(3, L::Partial(3).Size<0>());
- EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
- EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
- EXPECT_EQ(3, L(3, 5).Size<0>());
- EXPECT_EQ(5, L(3, 5).Size<1>());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(3, L::Partial(3).Size<0>());
- EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
- EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
- EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());
- EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());
- EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());
- EXPECT_EQ(3, L(3, 5, 7).Size<0>());
- EXPECT_EQ(5, L(3, 5, 7).Size<1>());
- EXPECT_EQ(7, L(3, 5, 7).Size<2>());
- }
- }
- TEST(Layout, SizeByType) {
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).Size<int32_t>());
- EXPECT_EQ(3, L::Partial(3).Size<int32_t>());
- EXPECT_EQ(3, L(3).Size<int32_t>());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(3, L::Partial(3).Size<int8_t>());
- EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());
- EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());
- EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());
- EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());
- EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());
- EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());
- EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());
- EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());
- }
- }
- TEST(Layout, Sizes) {
- {
- using L = Layout<int32_t>;
- EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
- EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
- EXPECT_THAT(L(3).Sizes(), ElementsAre(3));
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
- EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
- EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
- EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
- EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
- EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
- EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
- EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
- }
- }
- TEST(Layout, PointerByIndex) {
- alignas(max_align_t) const unsigned char p[100] = {};
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
- EXPECT_EQ(12,
- Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
- EXPECT_EQ(
- 12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
- EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
- EXPECT_EQ(4,
- Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
- EXPECT_EQ(
- 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
- EXPECT_EQ(
- 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
- EXPECT_EQ(24,
- Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
- EXPECT_EQ(
- 4,
- Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
- EXPECT_EQ(
- 8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
- EXPECT_EQ(
- 24,
- Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
- EXPECT_EQ(
- 8,
- Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
- EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
- EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
- }
- }
- TEST(Layout, PointerByType) {
- alignas(max_align_t) const unsigned char p[100] = {};
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(
- 0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 4,
- Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 8,
- Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
- L::Partial(0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
- L::Partial(1, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 8,
- Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
- EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
- L::Partial(5, 3).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 24,
- Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
- L::Partial(0, 0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
- L::Partial(0, 0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<const Int128*>(
- L::Partial(0, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
- L::Partial(1, 0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
- L::Partial(1, 0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(8, Distance(p, Type<const Int128*>(
- L::Partial(1, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
- L::Partial(5, 3, 1).Pointer<int8_t>(p))));
- EXPECT_EQ(24, Distance(p, Type<const Int128*>(
- L::Partial(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
- L::Partial(5, 3, 1).Pointer<int32_t>(p))));
- EXPECT_EQ(24,
- Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(
- 8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
- }
- }
- TEST(Layout, MutablePointerByIndex) {
- alignas(max_align_t) unsigned char p[100];
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
- EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
- EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));
- EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));
- EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
- EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
- EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
- EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
- EXPECT_EQ(4,
- Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
- EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
- EXPECT_EQ(24,
- Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
- EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
- }
- }
- TEST(Layout, MutablePointerByType) {
- alignas(max_align_t) unsigned char p[100];
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
- EXPECT_EQ(4,
- Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
- EXPECT_EQ(24,
- Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 4,
- Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(
- 8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
- EXPECT_EQ(
- 24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(
- 8,
- Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
- EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
- }
- }
- TEST(Layout, Pointers) {
- alignas(max_align_t) const unsigned char p[100] = {};
- using L = Layout<int8_t, int8_t, Int128>;
- {
- const auto x = L::Partial();
- EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
- Type<std::tuple<const int8_t*>>(x.Pointers(p)));
- }
- {
- const auto x = L::Partial(1);
- EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
- (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
- }
- {
- const auto x = L::Partial(1, 2);
- EXPECT_EQ(
- std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
- (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
- x.Pointers(p))));
- }
- {
- const auto x = L::Partial(1, 2, 3);
- EXPECT_EQ(
- std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
- (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
- x.Pointers(p))));
- }
- {
- const L x(1, 2, 3);
- EXPECT_EQ(
- std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
- (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
- x.Pointers(p))));
- }
- }
- TEST(Layout, MutablePointers) {
- alignas(max_align_t) unsigned char p[100];
- using L = Layout<int8_t, int8_t, Int128>;
- {
- const auto x = L::Partial();
- EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
- Type<std::tuple<int8_t*>>(x.Pointers(p)));
- }
- {
- const auto x = L::Partial(1);
- EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
- (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));
- }
- {
- const auto x = L::Partial(1, 2);
- EXPECT_EQ(
- std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
- (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
- }
- {
- const auto x = L::Partial(1, 2, 3);
- EXPECT_EQ(
- std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
- (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
- }
- {
- const L x(1, 2, 3);
- EXPECT_EQ(
- std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
- (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
- }
- }
- TEST(Layout, SliceByIndexSize) {
- alignas(max_align_t) const unsigned char p[100] = {};
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
- EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
- EXPECT_EQ(3, L(3).Slice<0>(p).size());
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
- EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
- EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
- EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
- EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
- EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
- }
- }
- TEST(Layout, SliceByTypeSize) {
- alignas(max_align_t) const unsigned char p[100] = {};
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
- EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
- EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
- EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
- EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
- EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
- EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
- }
- }
- TEST(Layout, MutableSliceByIndexSize) {
- alignas(max_align_t) unsigned char p[100];
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
- EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
- EXPECT_EQ(3, L(3).Slice<0>(p).size());
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
- EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
- EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
- EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
- EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
- EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
- }
- }
- TEST(Layout, MutableSliceByTypeSize) {
- alignas(max_align_t) unsigned char p[100];
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
- EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
- EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
- EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
- EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
- EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
- EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
- EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
- EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
- }
- }
- TEST(Layout, SliceByIndexData) {
- alignas(max_align_t) const unsigned char p[100] = {};
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
- EXPECT_EQ(
- 12,
- Distance(
- p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
- EXPECT_EQ(
- 12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(
- p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(
- p,
- Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p,
- Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
- EXPECT_EQ(
- 24,
- Distance(
- p,
- Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p,
- Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
- EXPECT_EQ(
- 24,
- Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
- }
- }
- TEST(Layout, SliceByTypeData) {
- alignas(max_align_t) const unsigned char p[100] = {};
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
- .data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
- L::Partial(0, 0).Slice<int32_t>(p))
- .data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
- .data()));
- EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
- L::Partial(1, 0).Slice<int32_t>(p))
- .data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
- .data()));
- EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
- L::Partial(5, 3).Slice<int32_t>(p))
- .data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
- L::Partial(0, 0, 0).Slice<int8_t>(p))
- .data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
- L::Partial(0, 0, 0).Slice<int32_t>(p))
- .data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
- L::Partial(0, 0, 0).Slice<Int128>(p))
- .data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
- L::Partial(1, 0, 0).Slice<int8_t>(p))
- .data()));
- EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
- L::Partial(1, 0, 0).Slice<int32_t>(p))
- .data()));
- EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
- L::Partial(1, 0, 0).Slice<Int128>(p))
- .data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
- L::Partial(5, 3, 1).Slice<int8_t>(p))
- .data()));
- EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
- L::Partial(5, 3, 1).Slice<Int128>(p))
- .data()));
- EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
- L::Partial(5, 3, 1).Slice<int32_t>(p))
- .data()));
- EXPECT_EQ(
- 0,
- Distance(p,
- Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 24,
- Distance(p,
- Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
- }
- }
- TEST(Layout, MutableSliceByIndexData) {
- alignas(max_align_t) unsigned char p[100];
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
- EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
- }
- {
- using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
- EXPECT_EQ(
- 12,
- Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
- EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));
- EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 4, Distance(
- p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
- EXPECT_EQ(
- 8, Distance(
- p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
- EXPECT_EQ(
- 24, Distance(
- p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
- EXPECT_EQ(
- 8, Distance(
- p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
- EXPECT_EQ(24,
- Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
- EXPECT_EQ(8,
- Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
- }
- }
- TEST(Layout, MutableSliceByTypeData) {
- alignas(max_align_t) unsigned char p[100];
- {
- using L = Layout<int32_t>;
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
- }
- {
- using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p,
- Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p,
- Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(
- p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p,
- Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(
- p,
- Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p,
- Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 24,
- Distance(
- p,
- Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
- p,
- Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 24,
- Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
- }
- }
- MATCHER_P(IsSameSlice, slice, "") {
- return arg.size() == slice.size() && arg.data() == slice.data();
- }
- template <typename... M>
- class TupleMatcher {
- public:
- explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
- template <typename Tuple>
- bool MatchAndExplain(const Tuple& p,
- testing::MatchResultListener* /* listener */) const {
- static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
- return MatchAndExplainImpl(
- p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
- }
- // For the matcher concept. Left empty as we don't really need the diagnostics
- // right now.
- void DescribeTo(::std::ostream* os) const {}
- void DescribeNegationTo(::std::ostream* os) const {}
- private:
- template <typename Tuple, size_t... Is>
- bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {
- // Using std::min as a simple variadic "and".
- return std::min(
- {true, testing::SafeMatcherCast<
- const typename std::tuple_element<Is, Tuple>::type&>(
- std::get<Is>(matchers_))
- .Matches(std::get<Is>(p))...});
- }
- std::tuple<M...> matchers_;
- };
- template <typename... M>
- testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
- return testing::MakePolymorphicMatcher(
- TupleMatcher<M...>(std::move(matchers)...));
- }
- TEST(Layout, Slices) {
- alignas(max_align_t) const unsigned char p[100] = {};
- using L = Layout<int8_t, int8_t, Int128>;
- {
- const auto x = L::Partial();
- EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
- }
- {
- const auto x = L::Partial(1);
- EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),
- Tuple(IsSameSlice(x.Slice<0>(p))));
- }
- {
- const auto x = L::Partial(1, 2);
- EXPECT_THAT(
- (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
- }
- {
- const auto x = L::Partial(1, 2, 3);
- EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
- Span<const Int128>>>(x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
- IsSameSlice(x.Slice<2>(p))));
- }
- {
- const L x(1, 2, 3);
- EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
- Span<const Int128>>>(x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
- IsSameSlice(x.Slice<2>(p))));
- }
- }
- TEST(Layout, MutableSlices) {
- alignas(max_align_t) unsigned char p[100] = {};
- using L = Layout<int8_t, int8_t, Int128>;
- {
- const auto x = L::Partial();
- EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
- }
- {
- const auto x = L::Partial(1);
- EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),
- Tuple(IsSameSlice(x.Slice<0>(p))));
- }
- {
- const auto x = L::Partial(1, 2);
- EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
- }
- {
- const auto x = L::Partial(1, 2, 3);
- EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
- x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
- IsSameSlice(x.Slice<2>(p))));
- }
- {
- const L x(1, 2, 3);
- EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
- x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
- IsSameSlice(x.Slice<2>(p))));
- }
- }
- TEST(Layout, UnalignedTypes) {
- constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);
- alignas(max_align_t) unsigned char p[x.AllocSize() + 1];
- EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));
- }
- TEST(Layout, CustomAlignment) {
- constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);
- alignas(max_align_t) unsigned char p[x.AllocSize()];
- EXPECT_EQ(10, x.AllocSize());
- EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));
- }
- TEST(Layout, OverAligned) {
- constexpr size_t M = alignof(max_align_t);
- constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
- #ifdef __GNUC__
- // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug:
- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357
- __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()];
- #else
- alignas(2 * M) unsigned char p[x.AllocSize()];
- #endif
- EXPECT_EQ(2 * M + 3, x.AllocSize());
- EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
- }
- TEST(Layout, Alignment) {
- static_assert(Layout<int8_t>::Alignment() == 1, "");
- static_assert(Layout<int32_t>::Alignment() == 4, "");
- static_assert(Layout<Int64>::Alignment() == 8, "");
- static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
- static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
- static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
- static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
- static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
- static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
- static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
- }
- TEST(Layout, ConstexprPartial) {
- constexpr size_t M = alignof(max_align_t);
- constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
- static_assert(x.Partial(1).template Offset<1>() == 2 * M, "");
- }
- // [from, to)
- struct Region {
- size_t from;
- size_t to;
- };
- void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
- #ifdef ABSL_HAVE_ADDRESS_SANITIZER
- for (size_t i = 0; i != n; ++i) {
- EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
- }
- #endif
- }
- template <size_t N>
- void ExpectPoisoned(const unsigned char (&buf)[N],
- std::initializer_list<Region> reg) {
- size_t prev = 0;
- for (const Region& r : reg) {
- ExpectRegionPoisoned(buf + prev, r.from - prev, false);
- ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);
- prev = r.to;
- }
- ExpectRegionPoisoned(buf + prev, N - prev, false);
- }
- TEST(Layout, PoisonPadding) {
- using L = Layout<int8_t, Int64, int32_t, Int128>;
- constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
- {
- constexpr auto x = L::Partial();
- alignas(max_align_t) const unsigned char c[n] = {};
- x.PoisonPadding(c);
- EXPECT_EQ(x.Slices(c), x.Slices(c));
- ExpectPoisoned(c, {});
- }
- {
- constexpr auto x = L::Partial(1);
- alignas(max_align_t) const unsigned char c[n] = {};
- x.PoisonPadding(c);
- EXPECT_EQ(x.Slices(c), x.Slices(c));
- ExpectPoisoned(c, {{1, 8}});
- }
- {
- constexpr auto x = L::Partial(1, 2);
- alignas(max_align_t) const unsigned char c[n] = {};
- x.PoisonPadding(c);
- EXPECT_EQ(x.Slices(c), x.Slices(c));
- ExpectPoisoned(c, {{1, 8}});
- }
- {
- constexpr auto x = L::Partial(1, 2, 3);
- alignas(max_align_t) const unsigned char c[n] = {};
- x.PoisonPadding(c);
- EXPECT_EQ(x.Slices(c), x.Slices(c));
- ExpectPoisoned(c, {{1, 8}, {36, 40}});
- }
- {
- constexpr auto x = L::Partial(1, 2, 3, 4);
- alignas(max_align_t) const unsigned char c[n] = {};
- x.PoisonPadding(c);
- EXPECT_EQ(x.Slices(c), x.Slices(c));
- ExpectPoisoned(c, {{1, 8}, {36, 40}});
- }
- {
- constexpr L x(1, 2, 3, 4);
- alignas(max_align_t) const unsigned char c[n] = {};
- x.PoisonPadding(c);
- EXPECT_EQ(x.Slices(c), x.Slices(c));
- ExpectPoisoned(c, {{1, 8}, {36, 40}});
- }
- }
- TEST(Layout, DebugString) {
- {
- constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
- EXPECT_EQ("@0<signed char>(1)", x.DebugString());
- }
- {
- constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
- EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
- }
- {
- constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);
- EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
- x.DebugString());
- }
- {
- constexpr auto x =
- Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
- EXPECT_EQ(
- "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
- "@16" +
- Int128::Name() + "(16)",
- x.DebugString());
- }
- {
- constexpr auto x =
- Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
- EXPECT_EQ(
- "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
- "@16" +
- Int128::Name() + "(16)[4]",
- x.DebugString());
- }
- {
- constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
- EXPECT_EQ(
- "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
- "@16" +
- Int128::Name() + "(16)[4]",
- x.DebugString());
- }
- }
- TEST(Layout, CharTypes) {
- constexpr Layout<int32_t> x(1);
- alignas(max_align_t) char c[x.AllocSize()] = {};
- alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};
- alignas(max_align_t) signed char sc[x.AllocSize()] = {};
- alignas(max_align_t) const char cc[x.AllocSize()] = {};
- alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};
- alignas(max_align_t) const signed char csc[x.AllocSize()] = {};
- Type<int32_t*>(x.Pointer<0>(c));
- Type<int32_t*>(x.Pointer<0>(uc));
- Type<int32_t*>(x.Pointer<0>(sc));
- Type<const int32_t*>(x.Pointer<0>(cc));
- Type<const int32_t*>(x.Pointer<0>(cuc));
- Type<const int32_t*>(x.Pointer<0>(csc));
- Type<int32_t*>(x.Pointer<int32_t>(c));
- Type<int32_t*>(x.Pointer<int32_t>(uc));
- Type<int32_t*>(x.Pointer<int32_t>(sc));
- Type<const int32_t*>(x.Pointer<int32_t>(cc));
- Type<const int32_t*>(x.Pointer<int32_t>(cuc));
- Type<const int32_t*>(x.Pointer<int32_t>(csc));
- Type<std::tuple<int32_t*>>(x.Pointers(c));
- Type<std::tuple<int32_t*>>(x.Pointers(uc));
- Type<std::tuple<int32_t*>>(x.Pointers(sc));
- Type<std::tuple<const int32_t*>>(x.Pointers(cc));
- Type<std::tuple<const int32_t*>>(x.Pointers(cuc));
- Type<std::tuple<const int32_t*>>(x.Pointers(csc));
- Type<Span<int32_t>>(x.Slice<0>(c));
- Type<Span<int32_t>>(x.Slice<0>(uc));
- Type<Span<int32_t>>(x.Slice<0>(sc));
- Type<Span<const int32_t>>(x.Slice<0>(cc));
- Type<Span<const int32_t>>(x.Slice<0>(cuc));
- Type<Span<const int32_t>>(x.Slice<0>(csc));
- Type<std::tuple<Span<int32_t>>>(x.Slices(c));
- Type<std::tuple<Span<int32_t>>>(x.Slices(uc));
- Type<std::tuple<Span<int32_t>>>(x.Slices(sc));
- Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));
- Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));
- Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));
- }
- TEST(Layout, ConstElementType) {
- constexpr Layout<const int32_t> x(1);
- alignas(int32_t) char c[x.AllocSize()] = {};
- const char* cc = c;
- const int32_t* p = reinterpret_cast<const int32_t*>(cc);
- EXPECT_EQ(alignof(int32_t), x.Alignment());
- EXPECT_EQ(0, x.Offset<0>());
- EXPECT_EQ(0, x.Offset<const int32_t>());
- EXPECT_THAT(x.Offsets(), ElementsAre(0));
- EXPECT_EQ(1, x.Size<0>());
- EXPECT_EQ(1, x.Size<const int32_t>());
- EXPECT_THAT(x.Sizes(), ElementsAre(1));
- EXPECT_EQ(sizeof(int32_t), x.AllocSize());
- EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));
- EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));
- EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));
- EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));
- EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));
- EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));
- EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),
- IsSameSlice(Span<const int32_t>(p, 1)));
- EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),
- IsSameSlice(Span<const int32_t>(p, 1)));
- EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),
- IsSameSlice(Span<const int32_t>(p, 1)));
- EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),
- IsSameSlice(Span<const int32_t>(p, 1)));
- EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),
- Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
- EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),
- Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
- }
- namespace example {
- // Immutable move-only string with sizeof equal to sizeof(void*). The string
- // size and the characters are kept in the same heap allocation.
- class CompactString {
- public:
- CompactString(const char* s = "") { // NOLINT
- const size_t size = strlen(s);
- // size_t[1], followed by char[size + 1].
- // This statement doesn't allocate memory.
- const L layout(1, size + 1);
- // AllocSize() tells us how much memory we need to allocate for all our
- // data.
- p_.reset(new unsigned char[layout.AllocSize()]);
- // If running under ASAN, mark the padding bytes, if any, to catch memory
- // errors.
- layout.PoisonPadding(p_.get());
- // Store the size in the allocation.
- // Pointer<size_t>() is a synonym for Pointer<0>().
- *layout.Pointer<size_t>(p_.get()) = size;
- // Store the characters in the allocation.
- memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
- }
- size_t size() const {
- // Equivalent to reinterpret_cast<size_t&>(*p).
- return *L::Partial().Pointer<size_t>(p_.get());
- }
- const char* c_str() const {
- // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
- // The argument in Partial(1) specifies that we have size_t[1] in front of
- // the characters.
- return L::Partial(1).Pointer<char>(p_.get());
- }
- private:
- // Our heap allocation contains a size_t followed by an array of chars.
- using L = Layout<size_t, char>;
- std::unique_ptr<unsigned char[]> p_;
- };
- TEST(CompactString, Works) {
- CompactString s = "hello";
- EXPECT_EQ(5, s.size());
- EXPECT_STREQ("hello", s.c_str());
- }
- } // namespace example
- } // namespace
- } // namespace container_internal
- ABSL_NAMESPACE_END
- } // namespace absl
|