hb-iter.hh (32141B)
1 /* 2 * Copyright © 2018 Google, Inc. 3 * Copyright © 2019 Facebook, Inc. 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Google Author(s): Behdad Esfahbod 26 * Facebook Author(s): Behdad Esfahbod 27 */ 28 29 #ifndef HB_ITER_HH 30 #define HB_ITER_HH 31 32 #include "hb.hh" 33 #include "hb-algs.hh" 34 #include "hb-meta.hh" 35 36 37 /* Unified iterator object. 38 * 39 * The goal of this template is to make the same iterator interface 40 * available to all types, and make it very easy and compact to use. 41 * hb_iter_tator objects are small, light-weight, objects that can be 42 * copied by value. If the collection / object being iterated on 43 * is writable, then the iterator returns lvalues, otherwise it 44 * returns rvalues. 45 * 46 * If iterator implementation implements operator!=, then it can be 47 * used in range-based for loop. That already happens if the iterator 48 * is random-access. Otherwise, the range-based for loop incurs 49 * one traversal to find end(), which can be avoided if written 50 * as a while-style for loop, or if iterator implements a faster 51 * __end__() method. */ 52 53 /* 54 * Base classes for iterators. 55 */ 56 57 /* Base class for all iterators. */ 58 template <typename iter_t, typename Item = typename iter_t::__item_t__> 59 struct hb_iter_t 60 { 61 typedef Item item_t; 62 constexpr unsigned get_item_size () const { return hb_static_size (Item); } 63 static constexpr bool is_iterator = true; 64 static constexpr bool is_random_access_iterator = false; 65 static constexpr bool is_sorted_iterator = false; 66 static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator. 67 68 private: 69 /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ 70 const iter_t* thiz () const { return static_cast<const iter_t *> (this); } 71 iter_t* thiz () { return static_cast< iter_t *> (this); } 72 public: 73 74 /* Operators. */ 75 iter_t iter () const { return *thiz(); } 76 iter_t operator + () const { return *thiz(); } 77 iter_t _begin () const { return *thiz(); } 78 iter_t begin () const { return _begin (); } 79 iter_t _end () const { return thiz()->__end__ (); } 80 iter_t end () const { return _end (); } 81 explicit operator bool () const { return thiz()->__more__ (); } 82 unsigned len () const { return thiz()->__len__ (); } 83 /* The following can only be enabled if item_t is reference type. Otherwise 84 * it will be returning pointer to temporary rvalue. */ 85 template <typename T = item_t, 86 hb_enable_if (std::is_reference<T>::value)> 87 hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); } 88 item_t operator * () const { return thiz()->__item__ (); } 89 item_t operator * () { return thiz()->__item__ (); } 90 item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); } 91 item_t operator [] (unsigned i) { return thiz()->__item_at__ (i); } 92 iter_t& operator += (unsigned count) & { thiz()->__forward__ (count); return *thiz(); } 93 iter_t operator += (unsigned count) && { thiz()->__forward__ (count); return *thiz(); } 94 iter_t& operator ++ () & { thiz()->__next__ (); return *thiz(); } 95 iter_t operator ++ () && { thiz()->__next__ (); return *thiz(); } 96 iter_t& operator -= (unsigned count) & { thiz()->__rewind__ (count); return *thiz(); } 97 iter_t operator -= (unsigned count) && { thiz()->__rewind__ (count); return *thiz(); } 98 iter_t& operator -- () & { thiz()->__prev__ (); return *thiz(); } 99 iter_t operator -- () && { thiz()->__prev__ (); return *thiz(); } 100 iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; } 101 friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; } 102 iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; } 103 iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; } 104 iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; } 105 template <typename T> 106 iter_t& operator >> (T &v) & { v = **thiz(); ++*thiz(); return *thiz(); } 107 template <typename T> 108 iter_t operator >> (T &v) && { v = **thiz(); ++*thiz(); return *thiz(); } 109 template <typename T> 110 iter_t& operator << (const T v) & { **thiz() = v; ++*thiz(); return *thiz(); } 111 template <typename T> 112 iter_t operator << (const T v) && { **thiz() = v; ++*thiz(); return *thiz(); } 113 114 protected: 115 hb_iter_t () = default; 116 hb_iter_t (const hb_iter_t &o HB_UNUSED) = default; 117 hb_iter_t (hb_iter_t &&o HB_UNUSED) = default; 118 hb_iter_t& operator = (const hb_iter_t &o HB_UNUSED) = default; 119 hb_iter_t& operator = (hb_iter_t &&o HB_UNUSED) = default; 120 }; 121 122 #define HB_ITER_USING(Name) \ 123 using item_t = typename Name::item_t; \ 124 using Name::_begin; \ 125 using Name::begin; \ 126 using Name::_end; \ 127 using Name::end; \ 128 using Name::get_item_size; \ 129 using Name::is_iterator; \ 130 using Name::iter; \ 131 using Name::operator bool; \ 132 using Name::len; \ 133 using Name::operator ->; \ 134 using Name::operator *; \ 135 using Name::operator []; \ 136 using Name::operator +=; \ 137 using Name::operator ++; \ 138 using Name::operator -=; \ 139 using Name::operator --; \ 140 using Name::operator +; \ 141 using Name::operator -; \ 142 using Name::operator >>; \ 143 using Name::operator <<; \ 144 static_assert (true, "") 145 146 /* Returns iterator / item type of a type. */ 147 template <typename Iterable> 148 using hb_iter_type = decltype (hb_deref (hb_declval (Iterable)).iter ()); 149 template <typename Iterable> 150 using hb_item_type = decltype (*hb_deref (hb_declval (Iterable)).iter ()); 151 152 153 template <typename> struct hb_array_t; 154 template <typename> struct hb_sorted_array_t; 155 156 struct 157 { 158 template <typename T> hb_iter_type<T> 159 operator () (T&& c) const 160 { return hb_deref (std::forward<T> (c)).iter (); } 161 162 /* Specialization for C arrays. */ 163 164 template <typename Type> inline hb_array_t<Type> 165 operator () (Type *array, unsigned int length) const 166 { return hb_array_t<Type> (array, length); } 167 168 template <typename Type, unsigned int length> hb_array_t<Type> 169 operator () (Type (&array)[length]) const 170 { return hb_array_t<Type> (array, length); } 171 172 } 173 HB_FUNCOBJ (hb_iter); 174 struct 175 { 176 template <typename T> auto 177 impl (T&& c, hb_priority<1>) const HB_RETURN (unsigned, c.len ()) 178 179 template <typename T> auto 180 impl (T&& c, hb_priority<0>) const HB_RETURN (unsigned, c.len) 181 182 public: 183 184 template <typename T> auto 185 operator () (T&& c) const HB_RETURN (unsigned, impl (std::forward<T> (c), hb_prioritize)) 186 } 187 HB_FUNCOBJ (hb_len); 188 189 /* Mixin to fill in what the subclass doesn't provide. */ 190 template <typename iter_t, typename item_t = typename iter_t::__item_t__> 191 struct hb_iter_fallback_mixin_t 192 { 193 private: 194 /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ 195 const iter_t* thiz () const { return static_cast<const iter_t *> (this); } 196 iter_t* thiz () { return static_cast< iter_t *> (this); } 197 public: 198 199 /* Access: Implement __item__(), or __item_at__() if random-access. */ 200 item_t __item__ () const { return (*thiz())[0]; } 201 item_t __item_at__ (unsigned i) const { return *(*thiz() + i); } 202 203 /* Termination: Implement __more__(), or __len__() if random-access. */ 204 bool __more__ () const { return bool (thiz()->len ()); } 205 unsigned __len__ () const 206 { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; } return l; } 207 208 /* Advancing: Implement __next__(), or __forward__() if random-access. */ 209 void __next__ () { *thiz() += 1; } 210 void __forward__ (unsigned n) { while (*thiz() && n--) ++*thiz(); } 211 212 /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */ 213 void __prev__ () { *thiz() -= 1; } 214 void __rewind__ (unsigned n) { while (*thiz() && n--) --*thiz(); } 215 216 /* Range-based for: Implement __end__() if can be done faster, 217 * and operator!=. */ 218 iter_t __end__ () const 219 { 220 if (thiz()->is_random_access_iterator) 221 return *thiz() + thiz()->len (); 222 /* Above expression loops twice. Following loops once. */ 223 auto it = *thiz(); 224 while (it) ++it; 225 return it; 226 } 227 228 protected: 229 hb_iter_fallback_mixin_t () = default; 230 hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default; 231 hb_iter_fallback_mixin_t (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default; 232 hb_iter_fallback_mixin_t& operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default; 233 hb_iter_fallback_mixin_t& operator = (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default; 234 }; 235 236 template <typename iter_t, typename item_t = typename iter_t::__item_t__> 237 struct hb_iter_with_fallback_t : 238 hb_iter_t<iter_t, item_t>, 239 hb_iter_fallback_mixin_t<iter_t, item_t> 240 { 241 protected: 242 hb_iter_with_fallback_t () = default; 243 hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) = default; 244 hb_iter_with_fallback_t (hb_iter_with_fallback_t &&o HB_UNUSED) = default; 245 hb_iter_with_fallback_t& operator = (const hb_iter_with_fallback_t &o HB_UNUSED) = default; 246 hb_iter_with_fallback_t& operator = (hb_iter_with_fallback_t &&o HB_UNUSED) = default; 247 }; 248 249 /* 250 * Meta-programming predicates. 251 */ 252 253 /* hb_is_iterator() / hb_is_iterator_of() */ 254 255 template<typename Iter, typename Item> 256 struct hb_is_iterator_of 257 { 258 template <typename Item2 = Item> 259 static hb_true_type impl (hb_priority<2>, hb_iter_t<Iter, hb_type_identity<Item2>> *); 260 static hb_false_type impl (hb_priority<0>, const void *); 261 262 public: 263 static constexpr bool value = decltype (impl (hb_prioritize, hb_declval (Iter*)))::value; 264 }; 265 #define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value 266 #define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t) 267 #define hb_is_sorted_iterator_of(Iter, Item) (hb_is_iterator_of<Iter, Item>::value && Iter::is_sorted_iterator) 268 #define hb_is_sorted_iterator(Iter) hb_is_sorted_iterator_of (Iter, typename Iter::item_t) 269 270 /* hb_is_iterable() */ 271 272 template <typename T> 273 struct hb_is_iterable 274 { 275 private: 276 277 template <typename U> 278 static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_type ()); 279 280 template <typename> 281 static hb_false_type impl (hb_priority<0>); 282 283 public: 284 static constexpr bool value = decltype (impl<T> (hb_prioritize))::value; 285 }; 286 #define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value 287 288 /* hb_is_source_of() / hb_is_sink_of() */ 289 290 template<typename Iter, typename Item> 291 struct hb_is_source_of 292 { 293 private: 294 template <typename Iter2 = Iter, 295 hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<const Item>))> 296 static hb_true_type impl (hb_priority<2>); 297 template <typename Iter2 = Iter> 298 static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ()); 299 static hb_false_type impl (hb_priority<0>); 300 301 public: 302 static constexpr bool value = decltype (impl (hb_prioritize))::value; 303 }; 304 #define hb_is_source_of(Iter, Item) hb_is_source_of<Iter, Item>::value 305 306 template<typename Iter, typename Item> 307 struct hb_is_sink_of 308 { 309 private: 310 template <typename Iter2 = Iter, 311 hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<Item>))> 312 static hb_true_type impl (hb_priority<2>); 313 template <typename Iter2 = Iter> 314 static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) << hb_declval (Item), hb_true_type ()); 315 static hb_false_type impl (hb_priority<0>); 316 317 public: 318 static constexpr bool value = decltype (impl (hb_prioritize))::value; 319 }; 320 #define hb_is_sink_of(Iter, Item) hb_is_sink_of<Iter, Item>::value 321 322 /* This is commonly used, so define: */ 323 #define hb_is_sorted_source_of(Iter, Item) \ 324 (hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator) 325 326 327 struct 328 { 329 template <typename Iterable, 330 hb_requires (hb_is_iterable (Iterable))> 331 unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); } 332 333 unsigned operator () (unsigned _) const { return _; } 334 } 335 HB_FUNCOBJ (hb_len_of); 336 337 /* Range-based 'for' for iterables. */ 338 339 template <typename Iterable, 340 hb_requires (hb_is_iterable (Iterable))> 341 static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ()) 342 343 template <typename Iterable, 344 hb_requires (hb_is_iterable (Iterable))> 345 static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ()) 346 347 /* begin()/end() are NOT looked up non-ADL. So each namespace must declare them. 348 * Do it for namespace OT. */ 349 namespace OT { 350 351 template <typename Iterable, 352 hb_requires (hb_is_iterable (Iterable))> 353 static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ()) 354 355 template <typename Iterable, 356 hb_requires (hb_is_iterable (Iterable))> 357 static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ()) 358 359 } 360 361 362 /* 363 * Adaptors, combiners, etc. 364 */ 365 366 template <typename Lhs, typename Rhs, 367 hb_requires (hb_is_iterator (Lhs))> 368 static inline auto 369 operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (std::forward<Rhs> (rhs) (std::forward<Lhs> (lhs))) 370 371 /* hb_map(), hb_filter(), hb_reduce() */ 372 373 enum class hb_function_sortedness_t { 374 NOT_SORTED, 375 RETAINS_SORTING, 376 SORTED, 377 }; 378 379 template <typename Iter, typename Proj, hb_function_sortedness_t Sorted, 380 hb_requires (hb_is_iterator (Iter))> 381 struct hb_map_iter_t : 382 hb_iter_t<hb_map_iter_t<Iter, Proj, Sorted>, 383 decltype (hb_get (hb_declval (Proj), *hb_declval (Iter)))> 384 { 385 hb_map_iter_t (const Iter& it, Proj f_) : it (it), f (f_) {} 386 387 typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__; 388 static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; 389 static constexpr bool is_sorted_iterator = 390 Sorted == hb_function_sortedness_t::SORTED ? true : 391 Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator : 392 false; 393 __item_t__ __item__ () const { return hb_get (f.get (), *it); } 394 __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); } 395 bool __more__ () const { return bool (it); } 396 unsigned __len__ () const { return it.len (); } 397 void __next__ () { ++it; } 398 void __forward__ (unsigned n) { it += n; } 399 void __prev__ () { --it; } 400 void __rewind__ (unsigned n) { it -= n; } 401 hb_map_iter_t __end__ () const { return hb_map_iter_t (it._end (), f); } 402 bool operator != (const hb_map_iter_t& o) const 403 { return it != o.it; } 404 405 private: 406 Iter it; 407 mutable hb_reference_wrapper<Proj> f; 408 }; 409 410 template <typename Proj, hb_function_sortedness_t Sorted> 411 struct hb_map_iter_factory_t 412 { 413 hb_map_iter_factory_t (Proj f) : f (f) {} 414 415 template <typename Iter, 416 hb_requires (hb_is_iterator (Iter))> 417 hb_map_iter_t<Iter, Proj, Sorted> 418 operator () (Iter it) 419 { return hb_map_iter_t<Iter, Proj, Sorted> (it, f); } 420 421 private: 422 Proj f; 423 }; 424 struct 425 { 426 template <typename Proj> 427 hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED> 428 operator () (Proj&& f) const 429 { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED> (f); } 430 } 431 HB_FUNCOBJ (hb_map); 432 struct 433 { 434 template <typename Proj> 435 hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING> 436 operator () (Proj&& f) const 437 { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING> (f); } 438 } 439 HB_FUNCOBJ (hb_map_retains_sorting); 440 struct 441 { 442 template <typename Proj> 443 hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED> 444 operator () (Proj&& f) const 445 { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED> (f); } 446 } 447 HB_FUNCOBJ (hb_map_sorted); 448 449 template <typename Iter, typename Pred, typename Proj, 450 hb_requires (hb_is_iterator (Iter))> 451 struct hb_filter_iter_t : 452 hb_iter_with_fallback_t<hb_filter_iter_t<Iter, Pred, Proj>, 453 typename Iter::item_t> 454 { 455 hb_filter_iter_t (const Iter& it_, Pred p_, Proj f_) : it (it_), p (p_), f (f_) 456 { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; } 457 458 typedef typename Iter::item_t __item_t__; 459 static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; 460 __item_t__ __item__ () const { return *it; } 461 bool __more__ () const { return bool (it); } 462 void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } 463 void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } 464 hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it._end (), p, f); } 465 bool operator != (const hb_filter_iter_t& o) const 466 { return it != o.it; } 467 468 private: 469 Iter it; 470 mutable hb_reference_wrapper<Pred> p; 471 mutable hb_reference_wrapper<Proj> f; 472 }; 473 template <typename Pred, typename Proj> 474 struct hb_filter_iter_factory_t 475 { 476 hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {} 477 478 template <typename Iter, 479 hb_requires (hb_is_iterator (Iter))> 480 hb_filter_iter_t<Iter, Pred, Proj> 481 operator () (Iter it) 482 { return hb_filter_iter_t<Iter, Pred, Proj> (it, p, f); } 483 484 private: 485 Pred p; 486 Proj f; 487 }; 488 struct 489 { 490 template <typename Pred = decltype ((hb_identity)), 491 typename Proj = decltype ((hb_identity))> 492 hb_filter_iter_factory_t<Pred, Proj> 493 operator () (Pred&& p = hb_identity, Proj&& f = hb_identity) const 494 { return hb_filter_iter_factory_t<Pred, Proj> (p, f); } 495 } 496 HB_FUNCOBJ (hb_filter); 497 498 template <typename Redu, typename InitT> 499 struct hb_reduce_t 500 { 501 hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {} 502 503 template <typename Iter, 504 hb_requires (hb_is_iterator (Iter)), 505 typename AccuT = hb_decay<decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>> 506 AccuT 507 operator () (Iter it) 508 { 509 AccuT value = init_value; 510 for (; it; ++it) 511 value = r (value, *it); 512 return value; 513 } 514 515 private: 516 Redu r; 517 InitT init_value; 518 }; 519 struct 520 { 521 template <typename Redu, typename InitT> 522 hb_reduce_t<Redu, InitT> 523 operator () (Redu&& r, InitT init_value) const 524 { return hb_reduce_t<Redu, InitT> (r, init_value); } 525 } 526 HB_FUNCOBJ (hb_reduce); 527 528 529 /* hb_zip() */ 530 531 template <typename A, typename B> 532 struct hb_zip_iter_t : 533 hb_iter_t<hb_zip_iter_t<A, B>, 534 hb_pair_t<typename A::item_t, typename B::item_t>> 535 { 536 hb_zip_iter_t () {} 537 hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {} 538 539 typedef hb_pair_t<typename A::item_t, typename B::item_t> __item_t__; 540 static constexpr bool is_random_access_iterator = 541 A::is_random_access_iterator && 542 B::is_random_access_iterator; 543 /* Note. The following categorization is only valid if A is strictly sorted, 544 * ie. does NOT have duplicates. Previously I tried to categorize sortedness 545 * more granularly, see commits: 546 * 547 * 513762849a683914fc266a17ddf38f133cccf072 548 * 4d3cf2adb669c345cc43832d11689271995e160a 549 * 550 * However, that was not enough, since hb_sorted_array_t, hb_sorted_vector_t, 551 * SortedArrayOf, etc all needed to be updated to add more variants. At that 552 * point I saw it not worth the effort, and instead we now deem all sorted 553 * collections as essentially strictly-sorted for the purposes of zip. 554 * 555 * The above assumption is not as bad as it sounds. Our "sorted" comes with 556 * no guarantees. It's just a contract, put in place to help you remember, 557 * and think about, whether an iterator you receive is expected to be 558 * sorted or not. As such, it's not perfect by definition, and should not 559 * be treated so. The inaccuracy here just errs in the direction of being 560 * more permissive, so your code compiles instead of erring on the side of 561 * marking your zipped iterator unsorted in which case your code won't 562 * compile. 563 * 564 * This semantical limitation does NOT affect logic in any other place I 565 * know of as of this writing. 566 */ 567 static constexpr bool is_sorted_iterator = A::is_sorted_iterator; 568 569 __item_t__ __item__ () const { return __item_t__ (*a, *b); } 570 __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); } 571 bool __more__ () const { return bool (a) && bool (b); } 572 unsigned __len__ () const { return hb_min (a.len (), b.len ()); } 573 void __next__ () { ++a; ++b; } 574 void __forward__ (unsigned n) { a += n; b += n; } 575 void __prev__ () { --a; --b; } 576 void __rewind__ (unsigned n) { a -= n; b -= n; } 577 hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a._end (), b._end ()); } 578 /* Note, we should stop if ANY of the iters reaches end. As such two compare 579 * unequal if both items are unequal, NOT if either is unequal. */ 580 bool operator != (const hb_zip_iter_t& o) const 581 { return a != o.a && b != o.b; } 582 583 private: 584 A a; 585 B b; 586 }; 587 struct 588 { HB_PARTIALIZE(2); 589 template <typename A, typename B, 590 hb_requires (hb_is_iterable (A) && hb_is_iterable (B))> 591 hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>> 592 operator () (A&& a, B&& b) const 593 { return hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); } 594 } 595 HB_FUNCOBJ (hb_zip); 596 597 /* hb_concat() */ 598 599 template <typename A, typename B> 600 struct hb_concat_iter_t : 601 hb_iter_t<hb_concat_iter_t<A, B>, typename A::item_t> 602 { 603 hb_concat_iter_t () {} 604 hb_concat_iter_t (A& a, B& b) : a (a), b (b) {} 605 hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {} 606 607 608 typedef typename A::item_t __item_t__; 609 static constexpr bool is_random_access_iterator = 610 A::is_random_access_iterator && 611 B::is_random_access_iterator; 612 static constexpr bool is_sorted_iterator = false; 613 614 __item_t__ __item__ () const 615 { 616 if (!a) 617 return *b; 618 return *a; 619 } 620 621 __item_t__ __item_at__ (unsigned i) const 622 { 623 unsigned a_len = a.len (); 624 if (i < a_len) 625 return a[i]; 626 return b[i - a_len]; 627 } 628 629 bool __more__ () const { return bool (a) || bool (b); } 630 631 unsigned __len__ () const { return a.len () + b.len (); } 632 633 void __next__ () 634 { 635 if (a) 636 ++a; 637 else 638 ++b; 639 } 640 641 void __forward__ (unsigned n) 642 { 643 if (!n) return; 644 if (!is_random_access_iterator) { 645 while (n-- && *this) { 646 (*this)++; 647 } 648 return; 649 } 650 651 unsigned a_len = a.len (); 652 if (n > a_len) { 653 n -= a_len; 654 a.__forward__ (a_len); 655 b.__forward__ (n); 656 } else { 657 a.__forward__ (n); 658 } 659 } 660 661 hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a._end (), b._end ()); } 662 bool operator != (const hb_concat_iter_t& o) const 663 { 664 return a != o.a 665 || b != o.b; 666 } 667 668 private: 669 A a; 670 B b; 671 }; 672 struct 673 { HB_PARTIALIZE(2); 674 template <typename A, typename B, 675 hb_requires (hb_is_iterable (A) && hb_is_iterable (B))> 676 hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> 677 operator () (A&& a, B&& b) const 678 { return hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); } 679 } 680 HB_FUNCOBJ (hb_concat); 681 682 /* hb_apply() */ 683 684 template <typename Appl> 685 struct hb_apply_t 686 { 687 hb_apply_t (Appl a) : a (a) {} 688 689 template <typename Iter, 690 hb_requires (hb_is_iterator (Iter))> 691 void operator () (Iter it) 692 { 693 for (; it; ++it) 694 (void) hb_invoke (a, *it); 695 } 696 697 private: 698 Appl a; 699 }; 700 struct 701 { 702 template <typename Appl> hb_apply_t<Appl> 703 operator () (Appl&& a) const 704 { return hb_apply_t<Appl> (a); } 705 706 template <typename Appl> hb_apply_t<Appl&> 707 operator () (Appl *a) const 708 { return hb_apply_t<Appl&> (*a); } 709 } 710 HB_FUNCOBJ (hb_apply); 711 712 /* hb_range()/hb_iota()/hb_repeat() */ 713 714 template <typename T, typename S> 715 struct hb_range_iter_t : 716 hb_iter_t<hb_range_iter_t<T, S>, T> 717 { 718 hb_range_iter_t (T start, T end_, S step) : v (start), end_ (end_for (start, end_, step)), step (step) {} 719 720 typedef T __item_t__; 721 static constexpr bool is_random_access_iterator = true; 722 static constexpr bool is_sorted_iterator = true; 723 __item_t__ __item__ () const { return hb_ridentity (v); } 724 __item_t__ __item_at__ (unsigned j) const { return v + j * step; } 725 bool __more__ () const { return v != end_; } 726 unsigned __len__ () const { return !step ? UINT_MAX : (end_ - v) / step; } 727 void __next__ () { v += step; } 728 void __forward__ (unsigned n) { v += n * step; } 729 void __prev__ () { v -= step; } 730 void __rewind__ (unsigned n) { v -= n * step; } 731 hb_range_iter_t __end__ () const { return hb_range_iter_t (end_, end_, step); } 732 bool operator != (const hb_range_iter_t& o) const 733 { return v != o.v; } 734 735 private: 736 static inline T end_for (T start, T end_, S step) 737 { 738 if (!step) 739 return end_; 740 auto res = (end_ - start) % step; 741 if (!res) 742 return end_; 743 end_ += step - res; 744 return end_; 745 } 746 747 private: 748 T v; 749 T end_; 750 S step; 751 }; 752 struct 753 { 754 template <typename T = unsigned> hb_range_iter_t<T, unsigned> 755 operator () (T end = (unsigned) -1) const 756 { return hb_range_iter_t<T, unsigned> (0, end, 1u); } 757 758 template <typename T, typename S = unsigned> hb_range_iter_t<T, S> 759 operator () (T start, T end, S step = 1u) const 760 { return hb_range_iter_t<T, S> (start, end, step); } 761 } 762 HB_FUNCOBJ (hb_range); 763 764 template <typename T, typename S> 765 struct hb_iota_iter_t : 766 hb_iter_with_fallback_t<hb_iota_iter_t<T, S>, T> 767 { 768 hb_iota_iter_t (T start, S step) : v (start), step (step) {} 769 770 private: 771 772 template <typename S2 = S> 773 auto 774 inc (hb_type_identity<S2> s, hb_priority<1>) 775 -> hb_void_t<decltype (hb_invoke (std::forward<hb_type_identity<S2>> (s), 776 hb_declval<T&> ()))> 777 { v = hb_invoke (std::forward<hb_type_identity<S2>> (s), v); } 778 779 void 780 inc (S s, hb_priority<0>) 781 { v += s; } 782 783 public: 784 785 typedef T __item_t__; 786 static constexpr bool is_random_access_iterator = true; 787 static constexpr bool is_sorted_iterator = true; 788 __item_t__ __item__ () const { return hb_ridentity (v); } 789 bool __more__ () const { return true; } 790 unsigned __len__ () const { return UINT_MAX; } 791 void __next__ () { inc (step, hb_prioritize); } 792 void __prev__ () { v -= step; } 793 hb_iota_iter_t __end__ () const { return *this; } 794 bool operator != (const hb_iota_iter_t& o) const { return true; } 795 796 private: 797 T v; 798 S step; 799 }; 800 struct 801 { 802 template <typename T = unsigned, typename S = unsigned> hb_iota_iter_t<T, S> 803 operator () (T start = 0u, S step = 1u) const 804 { return hb_iota_iter_t<T, S> (start, step); } 805 } 806 HB_FUNCOBJ (hb_iota); 807 808 template <typename T> 809 struct hb_repeat_iter_t : 810 hb_iter_t<hb_repeat_iter_t<T>, T> 811 { 812 hb_repeat_iter_t (T value) : v (value) {} 813 814 typedef T __item_t__; 815 static constexpr bool is_random_access_iterator = true; 816 static constexpr bool is_sorted_iterator = true; 817 __item_t__ __item__ () const { return v; } 818 __item_t__ __item_at__ (unsigned j) const { return v; } 819 bool __more__ () const { return true; } 820 unsigned __len__ () const { return UINT_MAX; } 821 void __next__ () {} 822 void __forward__ (unsigned) {} 823 void __prev__ () {} 824 void __rewind__ (unsigned) {} 825 hb_repeat_iter_t __end__ () const { return *this; } 826 bool operator != (const hb_repeat_iter_t& o) const { return true; } 827 828 private: 829 T v; 830 }; 831 struct 832 { 833 template <typename T> hb_repeat_iter_t<T> 834 operator () (T value) const 835 { return hb_repeat_iter_t<T> (value); } 836 } 837 HB_FUNCOBJ (hb_repeat); 838 839 /* hb_enumerate()/hb_take() */ 840 841 struct 842 { 843 template <typename Iterable, 844 typename Index = unsigned, 845 hb_requires (hb_is_iterable (Iterable))> 846 auto operator () (Iterable&& it, Index start = 0u) const HB_AUTO_RETURN 847 ( hb_zip (hb_iota (start), it) ) 848 } 849 HB_FUNCOBJ (hb_enumerate); 850 851 struct 852 { HB_PARTIALIZE(2); 853 template <typename Iterable, 854 hb_requires (hb_is_iterable (Iterable))> 855 auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN 856 ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) ) 857 858 /* Specialization arrays. */ 859 860 template <typename Type> inline hb_array_t<Type> 861 operator () (hb_array_t<Type> array, unsigned count) const 862 { return array.sub_array (0, count); } 863 864 template <typename Type> inline hb_sorted_array_t<Type> 865 operator () (hb_sorted_array_t<Type> array, unsigned count) const 866 { return array.sub_array (0, count); } 867 } 868 HB_FUNCOBJ (hb_take); 869 870 struct 871 { HB_PARTIALIZE(2); 872 template <typename Iter, 873 hb_requires (hb_is_iterator (Iter))> 874 auto operator () (Iter it, unsigned count) const HB_AUTO_RETURN 875 ( 876 + hb_iota (it, hb_add (count)) 877 | hb_map (hb_take (count)) 878 | hb_take ((hb_len (it) + count - 1) / count) 879 ) 880 } 881 HB_FUNCOBJ (hb_chop); 882 883 /* hb_sink() */ 884 885 template <typename Sink> 886 struct hb_sink_t 887 { 888 hb_sink_t (Sink s) : s (s) {} 889 890 template <typename Iter, 891 hb_requires (hb_is_iterator (Iter))> 892 void operator () (Iter it) 893 { 894 for (; it; ++it) 895 s << *it; 896 } 897 898 private: 899 Sink s; 900 }; 901 struct 902 { 903 template <typename Sink> hb_sink_t<Sink> 904 operator () (Sink&& s) const 905 { return hb_sink_t<Sink> (s); } 906 907 template <typename Sink> hb_sink_t<Sink&> 908 operator () (Sink *s) const 909 { return hb_sink_t<Sink&> (*s); } 910 } 911 HB_FUNCOBJ (hb_sink); 912 913 /* hb-drain: hb_sink to void / blackhole / /dev/null. */ 914 915 struct 916 { 917 template <typename Iter, 918 hb_requires (hb_is_iterator (Iter))> 919 void operator () (Iter it) const 920 { 921 for (; it; ++it) 922 (void) *it; 923 } 924 } 925 HB_FUNCOBJ (hb_drain); 926 927 /* hb_unzip(): unzip and sink to two sinks. */ 928 929 template <typename Sink1, typename Sink2> 930 struct hb_unzip_t 931 { 932 hb_unzip_t (Sink1 s1, Sink2 s2) : s1 (s1), s2 (s2) {} 933 934 template <typename Iter, 935 hb_requires (hb_is_iterator (Iter))> 936 void operator () (Iter it) 937 { 938 for (; it; ++it) 939 { 940 const auto &v = *it; 941 s1 << v.first; 942 s2 << v.second; 943 } 944 } 945 946 private: 947 Sink1 s1; 948 Sink2 s2; 949 }; 950 struct 951 { 952 template <typename Sink1, typename Sink2> hb_unzip_t<Sink1, Sink2> 953 operator () (Sink1&& s1, Sink2&& s2) const 954 { return hb_unzip_t<Sink1, Sink2> (s1, s2); } 955 956 template <typename Sink1, typename Sink2> hb_unzip_t<Sink1&, Sink2&> 957 operator () (Sink1 *s1, Sink2 *s2) const 958 { return hb_unzip_t<Sink1&, Sink2&> (*s1, *s2); } 959 } 960 HB_FUNCOBJ (hb_unzip); 961 962 963 /* hb-all, hb-any, hb-none. */ 964 965 struct 966 { 967 template <typename Iterable, 968 typename Pred = decltype ((hb_identity)), 969 typename Proj = decltype ((hb_identity)), 970 hb_requires (hb_is_iterable (Iterable))> 971 bool operator () (Iterable&& c, 972 Pred&& p = hb_identity, 973 Proj&& f = hb_identity) const 974 { 975 for (auto it = hb_iter (c); it; ++it) 976 if (!hb_match (p, hb_get (f, *it))) 977 return false; 978 return true; 979 } 980 } 981 HB_FUNCOBJ (hb_all); 982 struct 983 { 984 template <typename Iterable, 985 typename Pred = decltype ((hb_identity)), 986 typename Proj = decltype ((hb_identity)), 987 hb_requires (hb_is_iterable (Iterable))> 988 bool operator () (Iterable&& c, 989 Pred&& p = hb_identity, 990 Proj&& f = hb_identity) const 991 { 992 for (auto it = hb_iter (c); it; ++it) 993 if (hb_match (p, hb_get (f, *it))) 994 return true; 995 return false; 996 } 997 } 998 HB_FUNCOBJ (hb_any); 999 struct 1000 { 1001 template <typename Iterable, 1002 typename Pred = decltype ((hb_identity)), 1003 typename Proj = decltype ((hb_identity)), 1004 hb_requires (hb_is_iterable (Iterable))> 1005 bool operator () (Iterable&& c, 1006 Pred&& p = hb_identity, 1007 Proj&& f = hb_identity) const 1008 { 1009 for (auto it = hb_iter (c); it; ++it) 1010 if (hb_match (p, hb_get (f, *it))) 1011 return false; 1012 return true; 1013 } 1014 } 1015 HB_FUNCOBJ (hb_none); 1016 1017 /* 1018 * Algorithms operating on iterators. 1019 */ 1020 1021 template <typename C, typename V, 1022 hb_requires (hb_is_iterable (C))> 1023 inline void 1024 hb_fill (C&& c, const V &v) 1025 { 1026 for (auto i = hb_iter (c); i; i++) 1027 *i = v; 1028 } 1029 1030 template <typename S, typename D> 1031 inline void 1032 hb_copy (S&& is, D&& id) 1033 { 1034 hb_iter (is) | hb_sink (id); 1035 } 1036 1037 1038 #endif /* HB_ITER_HH */