Toleo la kwanza la skani, maktaba ya uchanganuzi wa maandishi kwa C++ yenye ujenzi wa mashine ya hali wakati wa kukusanya.

Toleo la kwanza la maktaba ya skani (0.1.0) limechapishwa. Linagawanya maandishi katika thamani kulingana na muundo wa muda wa kukusanya. Muundo au umbizo limeandikwa kama hoja ya kiolezo cha C++ na limekusanywa katika kiotomatiki cha finite kilichowekwa lebo (TDFA), ambacho upitishaji wake unafunuliwa hali kwa hali katika msimbo wa muda wa kukusanya kwa kutumia violezo vya C++. Matokeo ya utekelezaji ni thamani ya aina iliyoombwa. Msimbo wa mradi umeandikwa katika C++23 na unasambazwa chini ya leseni ya GPLv3. import scan; // Je, kamba nzima inalingana. Kila sehemu ya kuingia pia ni adapta ya masafa. scan::match<«[az]+@[az.]+»>(address); address | scan::match<«[az]+@[az.]+»>; // With groups. const auto found = scan::match<«([0-9]+)-([az]+)»>(«42-abc»); found.get<1>().to_view(); // "42" // Mwanzo wa mfuatano unaomilikiwa na muundo, na ulinganisho wa kwanza popote. scan::starts_with<«[a-z]+»>(«abc123»).whole().to_view(); // "abc" scan::search<«[0-9]+»>(«id=4210x»).to_view(); // "4210" // Ulinganisho wote na vipande vilivyo katikati ni mitazamo ya uvivu. for (const auto& one : text | scan::search_all<«[a-z]+»>) { … } const auto fields = "a,bb,,ccc" | scan::split<«,»> | std::ranges::to (); // Thamani, sio maandishi. panga safu mlalo { int id; std::string_view jina; }; const safu mlalo moja = skana::skana<«{},{[a-z]+}»>(mstari); // Orodha, jumla ya aina, umbo lililowekwa kwenye kiota. panga zote { std::vekta thamani; std::tofauti mkia; }; const all got = skani::skani<«{{}{*,?}} {{[0-9]+}|{[a-z]+}}»>(«1,2,3 abc»); // Mwanzo wa ingizo na kile kinachobaki. const auto [thamani, mapumziko] = skani::skani_kiambishi awali<«{},{}»>(line).take (); // Rekodi moja baada ya nyingine, kutoka kwa chochote. kwa (const row& one: scan::each<«{},{[a-z]+}\\n»>(text).of ()) { … }

Masafa ambayo yanaweza kusomwa mara moja tu husomwa bila kubafa, huku sehemu zilizokusanywa kadri herufi zinavyowasili. Idadi ya herufi za kushikilia imebainishwa na muundo wakati wa kukusanya; ambapo nambari hii haipatikani, usomaji hukataliwa wakati wa kukusanya. std::istringstream source(«set speed 42\nset gain 7\\n»); chanzo > std::noskipws; struct command { scan::held<16> name; int value; }; for (const command& one : scan::each<«set {[a-z]+} {[0-9]+}\\n»>(std::views::istream (chanzo)) .ya ()) { … } Utendaji.

Vipimo vilichukuliwa kwenye Ryzen 9 9950X, clang 22.1.8 na libc++, -O3 -march=native,LTO. 32 huandika kwa kila pasi, wastani wa pasi saba. "([az]+),([az]+),([az]+),([az]+),([az]+)" "alpha,bravo,charlie,delta,echo" scan::scan .sentinel() 477 ns re2c 554 ns skani::skani 659 ns CTRE 717 ns RE2 15986 ns sehemu zile zile tano, herufi mia mbili kila skani::skani .sentinel() 57.8 ns re2c 637 ns CTRE 692 ns RE2 11751 ns utambuzi wa "first.last@subdomain.example.com", hakuna kilichopatikana skani::match .sentinel().scalar() skana ya ns 436::match .scalar() 545 ns re2c 1186 ns RE2 2616 ns CTRE 14339 ns Kuvunja vikundi vinapochambuliwa

Aina huambiwa ni ya kundi gani kati ya makundi yake ambayo herufi inayofuata ni yake, na tathmini hufanywa mahali pake: hakuna marudio ya kitanzi yanayohifadhiwa, hakuna kamba ndogo zinazoundwa. kimuundo jumla { thamani ndefu isiyosainiwa = 0; }; usomaji wa muundo { nambari ya hesabu; std::string_view tail; }; template <> kimuundo skani::skani { constexpr tuli std::string_view pattern() { return R"(\\((_+)(X|Y)*)*\\))"; } struct statetype { unsigned long total = 0; unsigned place = 0, marks = 0; }; constexpr tuli statetype begin_groups() { return {}; } constexpr tuli void opened_group(state_type& one, scan::group_at<0>) { one.place = 0; one.marks = 0; } constexpr tuli void closed_group(state_type& one, scan::group_at<0>) { unsigned long weight = 1; for (unsigned step = 1; step < one.place; ++step) weight *= 10; one.total += weight * one.marks; } constexpr tuli void push_group(state_type& one, scan::group_at<1>, char) { ++one.place; } constexpr tuli void push_group(state_type& one, scan::group_at<2>, char letter) { one.marks += letter == 'Y' ? 2u: 1u; } constexpr tuli tally finish_groups(state_type one) { return {one.total}; } }; const reading got = scan::scan<“value={{[az]*}”>(“value=(__X_XX)abcdefgh”). ya (); // got.number.value == 12, got.tail == "abcdefgh"

skani ya hemp::skani .scalar() skani iliyoandikwa kwa mkono::skani 10 141 ns 41.4 ns 42.5 ns 170 ns 100 439 ns 341 ns 392 ns 1176 ns 1000 3314 ns 3170 ns 3797 ns 11887 ns
Muktadha na wagawaji

Kitu chochote cha mpigaji simu—kigawaji, bwawa, uwanja, chochote kile—kinaweza kupitishwa kwenye simu inayounda thamani. Aina ya muktadha haijapotea: hali ya skana na kila ndoano zake zinaweza kuwekwa kiolezo juu yake, kwa hivyo hakuna aina ya mpigaji simu iliyotajwa kwenye skana. struct arena { std::pmr::memory_resource* where = nullptr; std::pmr::memory_resource* resource() const { return where; } }; struct numbers { std::pmr::vekta thamani; }; panga zote mbili { nambari kushoto; nambari kulia; }; kiolezo <> panga muundo:: skana { static constexpr std::string_view pattern() { rudisha "([0-9]+)(?:,([0-9]+))*"; } kiolezo hali ya muundo {std::pmr::vekta thamani; int inayoendesha = 0; }; hali tuli begin_groups() { rudisha {}; } kiolezo inahitaji inahitaji(const Told& one) { one.resource(); } hali tuli vikundi_vya_kuanza(vilivyoandikwa Vilivyoambiwa& kuambiwa) { rudisha {std::pmr::vekta (told.resource()), 0}; } kiolezo kikundi_cha_kushinikiza_kilichosalia kisicho na utupu (hali na moja, skani::group_at , tarakimu ya herufi) { moja.inayoendesha = moja.inayoendesha * 10 + (tarakimu - '0'); } kiolezo kikundi_kitu kilichofungwa kisicho na utupu tuli (hali na moja, skani::group_at ) { one.values.push_back(one.running); one.running = 0; } template nambari tuli finish_groups(hali moja) { rudisha {std::move(one.values)}; } }; std::pmr::monotonic_buffer_resource baiti; const arena mine{&bytes}; skani::skani<“{} {}”>(text).of (yangu); // moja kwa sehemu zote mbili skana::skana<«{} {}»>(maandishi).ya (yangu, skani::muktadha_msingi); // moja kwa kila mahali skani::skani<“{} {}”>(maandishi).ya ({yangu, skani::default_context}); // sawa katika mabano const zote mbili zimepata = skani::skani<«{} {}»>(maandishi).na(yangu); // Muktadha sio lazima uwe wa aina yake: mgawaji huenda mbali kama // kujenga read. struct two { std::pmr::string name; std::pmr::string tail; }; const two keeped = skani::skani<«{[az]+} {[az]+}»>(maandishi).of<( std::pmr::polymorphic_allocator<>(&bytes));

Kiunganishi hupokea kitu cha mpigaji chenyewe, si nakala, kwa hivyo jimbo linaweza kuhifadhi anwani yake: muktadha huishi kwa muda mrefu kama wito, na usomaji wote hufanyika ndani ya wito huo. Sifa Nyingine

  • Tabaka mbili: safu ya kiolezo (linganisha, anza_na, tafuta, tafuta_yote, gawanya) na safu ya umbizo, ambapo "{}" ni sehemu, na thamani ya mahali huamuliwa na sehemu za aina yenyewe.
  • Kanuni ya kutenganisha utata iko upande wa kushoto zaidi, kama ilivyo katika Perl, RE2, na CTRE.
  • Yote hapo juu pia hufanya kazi katika usemi thabiti.
  • Hakuna upekuzi, marejeleo ya nyuma, au sifa za Unicode; templeti hufanya kazi kwenye baiti.
  • Mifumo inayojulikana tu wakati wa utekelezaji haitumiki.

Mkutano

Hukusanya na clang na GCC. Moduli za C++ ni za hiari: faili za kichwa (pamoja na/) zinazozalishwa kutoka kwa moduli zile zile na huduma ya demodulizer zinapatikana—kila kisukuma hadi kwenye ujenzi mpya mkuu, viungo, na kuvifanya viwekwe. Utegemezi pekee, Boost.PFR, hauhitajiki wakati vifurushi vya kufunga vya C++26 vimewezeshwa. FetchContent_Declare(scan GIT_REPOSITORY https://github.com/j4niwzis/scan.git GIT_TAG v0.1.0) FetchContent_MakeAvailable(scan) target_link_libraries(mine PRIVATE scan::scan)

Chanzo: opennet.ru

Nunua upangishaji wa kuaminika wa tovuti zilizo na ulinzi wa DDoS, seva za VPS VDS 🔥 Nunua upangishaji wa tovuti unaoaminika kwa ulinzi wa DDoS, seva za VPS VDS | ProHoster