298 lines
8.5 KiB
C
298 lines
8.5 KiB
C
/* MIT License
|
|
*
|
|
* Copyright (c) 2025 Tyge Løvset
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
// IWYU pragma: private
|
|
#ifndef _i_template
|
|
#define _i_template
|
|
|
|
#ifndef STC_TEMPLATE_H_INCLUDED
|
|
#define STC_TEMPLATE_H_INCLUDED
|
|
|
|
#define _c_MEMB(name) c_JOIN(Self, name)
|
|
#define _c_DEFTYPES(macro, SELF, ...) macro(SELF, __VA_ARGS__)
|
|
#define _m_value _c_MEMB(_value)
|
|
#define _m_key _c_MEMB(_key)
|
|
#define _m_mapped _c_MEMB(_mapped)
|
|
#define _m_rmapped _c_MEMB(_rmapped)
|
|
#define _m_raw _c_MEMB(_raw)
|
|
#define _m_keyraw _c_MEMB(_keyraw)
|
|
#define _m_iter _c_MEMB(_iter)
|
|
#define _m_result _c_MEMB(_result)
|
|
#define _m_node _c_MEMB(_node)
|
|
|
|
#define c_OPTION(flag) ((i_opt) & (flag))
|
|
#define c_declared (1<<0)
|
|
#define c_no_atomic (1<<1)
|
|
#define c_arc2 (1<<2)
|
|
#define c_no_clone (1<<3)
|
|
#define c_no_hash (1<<4)
|
|
#define c_use_cmp (1<<5)
|
|
#define c_use_eq (1<<6)
|
|
#define c_cmpclass (1<<7)
|
|
#define c_keyclass (1<<8)
|
|
#define c_valclass (1<<9)
|
|
#define c_keypro (1<<10)
|
|
#define c_valpro (1<<11)
|
|
#endif
|
|
|
|
#if defined i_rawclass // [deprecated]
|
|
#define i_cmpclass i_rawclass
|
|
#endif
|
|
|
|
#if defined T && !defined i_type
|
|
#define i_type T
|
|
#endif
|
|
#if defined i_type && c_NUMARGS(i_type) > 1
|
|
#define Self c_GETARG(1, i_type)
|
|
#define i_key c_GETARG(2, i_type)
|
|
#if c_NUMARGS(i_type) == 3
|
|
#if defined _i_is_map
|
|
#define i_val c_GETARG(3, i_type)
|
|
#else
|
|
#define i_opt c_GETARG(3, i_type)
|
|
#endif
|
|
#elif c_NUMARGS(i_type) == 4
|
|
#define i_val c_GETARG(3, i_type)
|
|
#define i_opt c_GETARG(4, i_type)
|
|
#endif
|
|
#elif !defined Self && defined i_type
|
|
#define Self i_type
|
|
#elif !defined Self
|
|
#define Self c_JOIN(_i_prefix, i_tag)
|
|
#endif
|
|
|
|
#if defined i_aux && c_NUMARGS(i_aux) == 2
|
|
// shorthand for defining i_aux AND i_allocator as a one-liner combo.
|
|
#define _i_aux_alloc
|
|
#define _i_aux_def c_GETARG(1, i_aux) aux;
|
|
#undef i_allocator // override:
|
|
#define i_allocator c_GETARG(2, i_aux)
|
|
#elif defined i_aux
|
|
#define _i_aux_def i_aux aux;
|
|
#else
|
|
#define _i_aux_def
|
|
#endif
|
|
|
|
#if c_OPTION(c_declared)
|
|
#define i_declared
|
|
#endif
|
|
#if c_OPTION(c_no_hash)
|
|
#define i_no_hash
|
|
#endif
|
|
#if c_OPTION(c_use_cmp)
|
|
#define i_use_cmp
|
|
#endif
|
|
#if c_OPTION(c_use_eq)
|
|
#define i_use_eq
|
|
#endif
|
|
#if c_OPTION(c_no_clone) || defined _i_is_arc
|
|
#define i_no_clone
|
|
#endif
|
|
#if c_OPTION(c_keyclass)
|
|
#define i_keyclass i_key
|
|
#endif
|
|
#if c_OPTION(c_valclass)
|
|
#define i_valclass i_val
|
|
#endif
|
|
#if c_OPTION(c_cmpclass)
|
|
#define i_cmpclass i_key
|
|
#define i_use_cmp
|
|
#endif
|
|
#if c_OPTION(c_keypro)
|
|
#define i_keypro i_key
|
|
#endif
|
|
#if c_OPTION(c_valpro)
|
|
#define i_valpro i_val
|
|
#endif
|
|
|
|
#if defined i_keypro
|
|
#define i_keyclass i_keypro
|
|
#define i_cmpclass c_JOIN(i_keypro, _raw)
|
|
#endif
|
|
|
|
#if defined i_cmpclass
|
|
#define i_keyraw i_cmpclass
|
|
#if !(defined i_key || defined i_keyclass)
|
|
#define i_key i_cmpclass
|
|
#endif
|
|
#elif defined i_keyclass && !defined i_keyraw
|
|
// Special: When only i_keyclass is defined, also define i_cmpclass to the same.
|
|
// Do not define i_keyraw here, otherwise _from() / _toraw() is expected to exist.
|
|
#define i_cmpclass i_key
|
|
#endif
|
|
|
|
// Bind to i_key "class members": _clone, _drop, _from and _toraw (when conditions are met).
|
|
#if defined i_keyclass
|
|
#ifndef i_key
|
|
#define i_key i_keyclass
|
|
#endif
|
|
#if !defined i_keyclone && !defined i_no_clone
|
|
#define i_keyclone c_JOIN(i_keyclass, _clone)
|
|
#endif
|
|
#ifndef i_keydrop
|
|
#define i_keydrop c_JOIN(i_keyclass, _drop)
|
|
#endif
|
|
#if !defined i_keyfrom && defined i_keyraw
|
|
#define i_keyfrom c_JOIN(i_keyclass, _from)
|
|
#endif
|
|
#if !defined i_keytoraw && defined i_keyraw
|
|
#define i_keytoraw c_JOIN(i_keyclass, _toraw)
|
|
#endif
|
|
#endif
|
|
|
|
// Define when container has support for sorting (cmp) and linear search (eq)
|
|
#if defined i_use_cmp || defined i_cmp || defined i_less
|
|
#define _i_has_cmp
|
|
#endif
|
|
#if defined i_use_cmp || defined i_cmp || defined i_use_eq || defined i_eq
|
|
#define _i_has_eq
|
|
#endif
|
|
|
|
// Bind to i_cmpclass "class members": _cmp, _eq and _hash (when conditions are met).
|
|
#if defined i_cmpclass
|
|
#if !(defined i_cmp || defined i_less) && (defined i_use_cmp || defined _i_sorted)
|
|
#define i_cmp c_JOIN(i_cmpclass, _cmp)
|
|
#endif
|
|
#if !defined i_eq && (defined i_use_eq || defined i_hash || defined _i_is_hash)
|
|
#define i_eq c_JOIN(i_cmpclass, _eq)
|
|
#endif
|
|
#if !(defined i_hash || defined i_no_hash)
|
|
#define i_hash c_JOIN(i_cmpclass, _hash)
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined i_key
|
|
#error "No i_key defined"
|
|
#elif defined i_keyraw && !(c_OPTION(c_cmpclass) || defined i_keytoraw)
|
|
#error "If i_cmpclass / i_keyraw is defined, i_keytoraw must be defined too"
|
|
#elif !defined i_no_clone && (defined i_keyclone ^ defined i_keydrop)
|
|
#error "Both i_keyclone and i_keydrop must be defined, if any (unless i_no_clone defined)."
|
|
#elif defined i_from || defined i_drop
|
|
#error "i_from / i_drop not supported. Use i_keyfrom/i_keydrop"
|
|
#elif defined i_keyto || defined i_valto
|
|
#error i_keyto / i_valto not supported. Use i_keytoraw / i_valtoraw
|
|
#elif defined i_keyraw && defined i_use_cmp && !defined _i_has_cmp
|
|
#error "For smap / sset / pqueue, i_cmp or i_less must be defined when i_keyraw is defined."
|
|
#endif
|
|
|
|
// Fill in missing i_eq, i_less, i_cmp functions with defaults.
|
|
#if !defined i_eq && defined i_cmp
|
|
#define i_eq(x, y) (i_cmp(x, y)) == 0
|
|
#elif !defined i_eq
|
|
#define i_eq(x, y) *x == *y // works for integral types
|
|
#endif
|
|
#if !defined i_less && defined i_cmp
|
|
#define i_less(x, y) (i_cmp(x, y)) < 0
|
|
#elif !defined i_less
|
|
#define i_less(x, y) *x < *y // works for integral types
|
|
#endif
|
|
#if !defined i_cmp && defined i_less
|
|
#define i_cmp(x, y) (i_less(y, x)) - (i_less(x, y))
|
|
#endif
|
|
#if !(defined i_hash || defined i_no_hash)
|
|
#define i_hash c_default_hash
|
|
#endif
|
|
|
|
#define i_no_emplace
|
|
|
|
#ifndef i_tag
|
|
#define i_tag i_key
|
|
#endif
|
|
#if !defined i_keyfrom
|
|
#define i_keyfrom c_default_clone
|
|
#else
|
|
#undef i_no_emplace
|
|
#endif
|
|
#ifndef i_keyraw
|
|
#define i_keyraw i_key
|
|
#endif
|
|
#ifndef i_keytoraw
|
|
#define i_keytoraw c_default_toraw
|
|
#endif
|
|
#ifndef i_keyclone
|
|
#define i_keyclone c_default_clone
|
|
#endif
|
|
#ifndef i_keydrop
|
|
#define i_keydrop c_default_drop
|
|
#endif
|
|
|
|
#if defined _i_is_map // ---- process hashmap/sortedmap value i_val, ... ----
|
|
|
|
#if defined i_valpro
|
|
#define i_valclass i_valpro
|
|
#define i_valraw c_JOIN(i_valpro, _raw)
|
|
#endif
|
|
|
|
#ifdef i_valclass
|
|
#ifndef i_val
|
|
#define i_val i_valclass
|
|
#endif
|
|
#if !defined i_valclone && !defined i_no_clone
|
|
#define i_valclone c_JOIN(i_valclass, _clone)
|
|
#endif
|
|
#ifndef i_valdrop
|
|
#define i_valdrop c_JOIN(i_valclass, _drop)
|
|
#endif
|
|
#if !defined i_valfrom && defined i_valraw
|
|
#define i_valfrom c_JOIN(i_valclass, _from)
|
|
#endif
|
|
#if !defined i_valtoraw && defined i_valraw
|
|
#define i_valtoraw c_JOIN(i_valclass, _toraw)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef i_val
|
|
#error "i_val* must be defined for maps"
|
|
#elif defined i_valraw && !defined i_valtoraw
|
|
#error "If i_valraw is defined, i_valtoraw must be defined too"
|
|
#elif !defined i_no_clone && (defined i_valclone ^ defined i_valdrop)
|
|
#error "Both i_valclone and i_valdrop must be defined, if any"
|
|
#endif
|
|
|
|
#if !defined i_valfrom
|
|
#define i_valfrom c_default_clone
|
|
#else
|
|
#undef i_no_emplace
|
|
#endif
|
|
#ifndef i_valraw
|
|
#define i_valraw i_val
|
|
#endif
|
|
#ifndef i_valtoraw
|
|
#define i_valtoraw c_default_toraw
|
|
#endif
|
|
#ifndef i_valclone
|
|
#define i_valclone c_default_clone
|
|
#endif
|
|
#ifndef i_valdrop
|
|
#define i_valdrop c_default_drop
|
|
#endif
|
|
|
|
#endif // !_i_is_map
|
|
|
|
#ifndef i_val
|
|
#define i_val i_key
|
|
#endif
|
|
#ifndef i_valraw
|
|
#define i_valraw i_keyraw
|
|
#endif
|
|
#endif // STC_TEMPLATE_H_INCLUDED
|