FastLED 3.10.6
Loading...
Searching...
No Matches
flat_map_basic.h
Go to the documentation of this file.
1#pragma once
2
3// flat_map_basic: type-erased binary-search core shared by all
4// `fl::flat_map<K, V, Less>` instantiations. The per-instantiation
5// binary-search code (`lower_bound`, `upper_bound`) is pure byte-arithmetic
6// + one comparator call per iteration; it does not depend on the K or V
7// types beyond their layout (`sizeof(pair<K,V>)`) and the comparator's
8// behavior. Sharing the loop across instantiations saves ~150 B per
9// distinct flat_map type at the cost of ~30-50 B per call site.
10//
11// Design pattern mirrors `fl::vector_basic`: the templated public
12// `flat_map<K, V, Less>` calls into the non-template helpers below
13// through a `flat_map_ops` parameter block that carries (a) a thunk
14// pointer that knows how to compare two `Key` values given their
15// addresses and (b) the element stride (`sizeof(pair<K,V>)`).
16//
17// Comparator state is passed via a `const void*` context pointer so
18// that stateful comparators (e.g. ones that capture string-intern
19// tables) are supported uniformly with stateless ones (`fl::less<T>`).
20// The thunk casts the context back to its concrete `Less*` and invokes
21// `(*less)(key_a, key_b)`. For `fl::pair<K, V>`, `.first` is at offset
22// 0 (standard layout) so the helpers can treat the storage as an array
23// of K-prefixed records and compare on the prefix directly.
24//
25// FL_NO_INLINE on the implementations is load-bearing: with LTO enabled
26// (default on every embedded target) the compiler would otherwise fold
27// the body back into each call site, defeating the whole dedup goal.
28//
29// See FastLED #3235 Tier 2D. Note: at small instantiation counts the
30// per-call thunk overhead can exceed the savings (sketches with 1-2
31// flat_map types see neutral-or-slightly-negative deltas). The win
32// scales with the number of distinct `flat_map<K,V,Less>` types in the
33// link, so the value materializes on kitchen-sink builds (WASM compiler
34// runtime, full RPC + audio + UI matrices) more than on focused
35// sketches.
36
37#include "fl/stl/int.h"
38#include "fl/stl/cstddef.h"
39#include "fl/stl/compiler_control.h" // for FL_NO_INLINE
40#include "fl/stl/noexcept.h"
41
42namespace fl {
43namespace detail {
44
45// Function-pointer-with-context comparator: returns true iff *a < *b.
46using flat_map_less_thunk_t = bool (*)(const void* ctx,
47 const void* a, const void* b) FL_NO_EXCEPT;
48
51 const void* less_ctx; // address of the owning flat_map's `mLess`
52 fl::size element_size; // sizeof(pair<K, V>)
53};
54
55// lower_bound returns the index of the first element in [0, n) whose
56// `.first` (a `Key` prefix at the start of each element) is NOT less
57// than `*key`. If no such element exists, returns `n`. Caller turns the
58// index back into an iterator via `begin() + idx`.
60fl::size flat_map_lower_bound_idx(const void* data, fl::size n,
61 const void* key,
62 const flat_map_ops& ops) FL_NO_EXCEPT;
63
64// upper_bound returns the index of the first element in [0, n) whose
65// `.first` is strictly greater than `*key` (equivalently: `less(*key,
66// elem.first)` is true).
68fl::size flat_map_upper_bound_idx(const void* data, fl::size n,
69 const void* key,
70 const flat_map_ops& ops) FL_NO_EXCEPT;
71
72} // namespace detail
73} // namespace fl
#define FL_NO_INLINE
bool(*)(const void *ctx, const void *a, const void *b) FL_NO_EXCEPT flat_map_less_thunk_t
FL_NO_INLINE fl::size flat_map_lower_bound_idx(const void *data, fl::size n, const void *key, const flat_map_ops &ops) FL_NO_EXCEPT
FL_NO_INLINE fl::size flat_map_upper_bound_idx(const void *data, fl::size n, const void *key, const flat_map_ops &ops) FL_NO_EXCEPT
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_info.h:57
flat_map_less_thunk_t less_fn
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
Base definition for an LED controller.
Definition crgb.hpp:179