LLVMFuzzerTestOneInput:
   13|  5.43k|{
   14|  5.43k|  if(size < 4)
  ------------------
  |  Branch (14:6): [True: 2, False: 5.42k]
  ------------------
   15|      2|  {
   16|      2|    return 0;
   17|      2|  }
   18|       |
   19|  5.42k|  FuzzedDataProvider fuzz_data(data, size);
   20|       |
   21|  5.42k|  try
   22|  5.42k|  {
   23|  5.42k|    BT::Ast::Environment env;
   24|  5.42k|    env.vars = BT::Blackboard::create();
   25|  5.42k|    env.enums = std::make_shared<BT::EnumsTable>();
   26|       |
   27|       |    // Add some test variables to the blackboard
   28|  5.42k|    env.vars->set("test_int", 42);
   29|  5.42k|    env.vars->set("test_double", 3.14);
   30|  5.42k|    env.vars->set("test_bool", true);
   31|  5.42k|    env.vars->set("test_string", std::string("test"));
   32|       |
   33|       |    // Add some test enums
   34|  5.42k|    (*env.enums)["RUNNING"] = 0;
   35|  5.42k|    (*env.enums)["SUCCESS"] = 1;
   36|  5.42k|    (*env.enums)["FAILURE"] = 2;
   37|       |
   38|  5.42k|    std::string script = fuzz_data.ConsumeRandomLengthString();
   39|       |
   40|  5.42k|    auto validation_result = BT::ValidateScript(script);
   41|       |
   42|  5.42k|    if(!validation_result)
  ------------------
  |  Branch (42:8): [True: 1.31k, False: 4.11k]
  ------------------
   43|  1.31k|    {
   44|  1.31k|      auto parsed_script = BT::ParseScript(script);
   45|  1.31k|      if(parsed_script)
  ------------------
  |  Branch (45:10): [True: 0, False: 1.31k]
  ------------------
   46|      0|      {
   47|      0|        try
   48|      0|        {
   49|      0|          auto result = parsed_script.value()(env);
   50|       |
   51|      0|          if(result.isNumber())
  ------------------
  |  Branch (51:14): [True: 0, False: 0]
  ------------------
   52|      0|          {
   53|      0|            volatile auto num = result.cast<double>();
   54|      0|          }
   55|       |
   56|      0|          env.vars->set("result", result);
   57|       |
   58|      0|          BT::Any read_back;
   59|      0|          (void)env.vars->get("result", read_back);
   60|      0|        }
   61|      0|        catch(const BT::RuntimeError&)  // NOLINT(bugprone-empty-catch)
   62|      0|        {
   63|       |          // Intentionally empty - fuzzer expects exceptions
   64|      0|        }
   65|      0|      }
   66|  1.31k|    }
   67|       |
   68|  5.42k|    BT::ParseScriptAndExecute(env, script);
   69|  5.42k|  }
   70|  5.42k|  catch(const std::exception&)  // NOLINT(bugprone-empty-catch)
   71|  5.42k|  {
   72|       |    // Intentionally empty - fuzzer expects exceptions
   73|    396|  }
   74|       |
   75|  5.42k|  return 0;
   76|  5.42k|}

_ZN2BT23GetAnyFromStringFunctorIiEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  217|  5.42k|{
  218|       |  if constexpr(std::is_constructible_v<StringView, T>)
  219|       |  {
  220|       |    return [](StringView str) { return Any(str); };
  221|       |  }
  222|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  223|       |  {
  224|       |    return {};
  225|       |  }
  226|       |  else
  227|  5.42k|  {
  228|  5.42k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  229|  5.42k|  }
  230|  5.42k|}
_ZN2BT8PortInfoC2ENS_13PortDirectionESt10type_indexSt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEE:
  411|  16.2k|    : TypeInfo(type_info, conv), direction_(direction)
  412|  16.2k|  {}
_ZN2BT8TypeInfoC2ESt10type_indexSt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEE:
  369|  16.2k|    : type_info_(type_info), converter_(conv), type_str_(BT::demangle(type_info))
  370|  16.2k|  {}
_ZN2BT23GetAnyFromStringFunctorIdEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  217|  5.42k|{
  218|       |  if constexpr(std::is_constructible_v<StringView, T>)
  219|       |  {
  220|       |    return [](StringView str) { return Any(str); };
  221|       |  }
  222|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  223|       |  {
  224|       |    return {};
  225|       |  }
  226|       |  else
  227|  5.42k|  {
  228|  5.42k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  229|  5.42k|  }
  230|  5.42k|}
_ZN2BT23GetAnyFromStringFunctorIbEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  217|  5.42k|{
  218|       |  if constexpr(std::is_constructible_v<StringView, T>)
  219|       |  {
  220|       |    return [](StringView str) { return Any(str); };
  221|       |  }
  222|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  223|       |  {
  224|       |    return {};
  225|       |  }
  226|       |  else
  227|  5.42k|  {
  228|  5.42k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  229|  5.42k|  }
  230|  5.42k|}
_ZN2BT8PortInfoC2ENS_13PortDirectionE:
  407|  15.3k|    : TypeInfo(), direction_(direction)
  408|  15.3k|  {}
_ZN2BT8TypeInfoC2Ev:
  365|  15.3k|  TypeInfo() : type_info_(typeid(AnyTypeAllowed)), type_str_("AnyTypeAllowed")
  366|  15.3k|  {}
_ZNK2BT8TypeInfo9converterEv:
  393|    828|  {
  394|    828|    return converter_;
  395|    828|  }

_ZN2BT10Blackboard6createESt10shared_ptrIS0_E:
   75|  5.42k|  {
   76|  5.42k|    return std::shared_ptr<Blackboard>(new Blackboard(parent));
   77|  5.42k|  }
_ZN2BT10BlackboardC2ESt10shared_ptrIS0_E:
   41|  5.42k|  Blackboard(Blackboard::Ptr parent) : parent_bb_(parent)
   42|  5.42k|  {}
_ZN2BT10BlackboardD2Ev:
   79|  5.42k|  virtual ~Blackboard() = default;
_ZN2BT10Blackboard3setIiEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  273|  5.42k|{
  274|  5.42k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.42k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.42k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.42k|  auto it = storage_.find(key);
  283|  5.42k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.42k, False: 0]
  ------------------
  284|  5.42k|  {
  285|       |    // create a new entry
  286|  5.42k|    Any new_value(value);
  287|  5.42k|    storage_lock.unlock();
  288|  5.42k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|       |    {
  292|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|  5.42k|    {
  296|  5.42k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|  5.42k|                        GetAnyFromStringFunctor<T>());
  298|  5.42k|      entry = createEntryImpl(key, new_port);
  299|  5.42k|    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.42k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.42k|    entry->value = new_value;
  305|  5.42k|    entry->sequence_id++;
  306|  5.42k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.42k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [Folded, False: 0]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|      0|      {
  354|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  |  Branch (354:27): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|        }
  358|      0|      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.42k|}
_ZN2BT10Blackboard3setIdEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  273|  5.42k|{
  274|  5.42k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.42k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.42k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.42k|  auto it = storage_.find(key);
  283|  5.42k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.42k, False: 0]
  ------------------
  284|  5.42k|  {
  285|       |    // create a new entry
  286|  5.42k|    Any new_value(value);
  287|  5.42k|    storage_lock.unlock();
  288|  5.42k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|       |    {
  292|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|  5.42k|    {
  296|  5.42k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|  5.42k|                        GetAnyFromStringFunctor<T>());
  298|  5.42k|      entry = createEntryImpl(key, new_port);
  299|  5.42k|    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.42k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.42k|    entry->value = new_value;
  305|  5.42k|    entry->sequence_id++;
  306|  5.42k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.42k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [Folded, False: 0]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|      0|      {
  354|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  |  Branch (354:27): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|        }
  358|      0|      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.42k|}
_ZN2BT10Blackboard3setIbEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  273|  5.42k|{
  274|  5.42k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.42k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.42k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.42k|  auto it = storage_.find(key);
  283|  5.42k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.42k, False: 0]
  ------------------
  284|  5.42k|  {
  285|       |    // create a new entry
  286|  5.42k|    Any new_value(value);
  287|  5.42k|    storage_lock.unlock();
  288|  5.42k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|       |    {
  292|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|  5.42k|    {
  296|  5.42k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|  5.42k|                        GetAnyFromStringFunctor<T>());
  298|  5.42k|      entry = createEntryImpl(key, new_port);
  299|  5.42k|    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.42k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.42k|    entry->value = new_value;
  305|  5.42k|    entry->sequence_id++;
  306|  5.42k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.42k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [Folded, False: 0]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|      0|      {
  354|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  |  Branch (354:27): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|        }
  358|      0|      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.42k|}
_ZN2BT10Blackboard3setINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvRKS7_RKT_:
  273|  5.42k|{
  274|  5.42k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.42k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.42k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.42k|  auto it = storage_.find(key);
  283|  5.42k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.42k, False: 0]
  ------------------
  284|  5.42k|  {
  285|       |    // create a new entry
  286|  5.42k|    Any new_value(value);
  287|  5.42k|    storage_lock.unlock();
  288|  5.42k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|  5.42k|    {
  292|  5.42k|      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|       |    {
  296|       |      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|       |                        GetAnyFromStringFunctor<T>());
  298|       |      entry = createEntryImpl(key, new_port);
  299|       |    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.42k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.42k|    entry->value = new_value;
  305|  5.42k|    entry->sequence_id++;
  306|  5.42k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.42k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [True: 0, Folded]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|       |      {
  354|       |        if(mismatching && isCastingSafe(previous_type, value))
  355|       |        {
  356|       |          mismatching = false;
  357|       |        }
  358|       |      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.42k|}
_ZN2BT10Blackboard5EntryC2ERKNS_8TypeInfoE:
   61|  31.6k|    Entry(const TypeInfo& _info) : info(_info)
   62|  31.6k|    {}
_ZN2BT10Blackboard5EntryD2Ev:
   64|  31.6k|    ~Entry() = default;

_ZNK4linb3any4typeEv:
  176|  1.79M|    {
  177|  1.79M|        return empty()? typeid(void) : this->vtable->type();
  ------------------
  |  Branch (177:16): [True: 4, False: 1.79M]
  ------------------
  178|  1.79M|    }
_ZNK4linb3any5emptyEv:
  169|  11.1M|    {
  170|  11.1M|        return this->vtable == nullptr;
  171|  11.1M|    }
_ZN4linb3anyC2Ev:
   72|  95.1k|        vtable(nullptr)
   73|  95.1k|    {
   74|  95.1k|    }
_ZN4linb3anyD2Ev:
  100|  5.21M|    {
  101|  5.21M|        this->clear();
  102|  5.21M|    }
_ZN4linb3any5clearEv:
  159|  5.21M|    {
  160|  5.21M|        if(!empty())
  ------------------
  |  Branch (160:12): [True: 3.62M, False: 1.59M]
  ------------------
  161|  3.62M|        {
  162|  3.62M|            this->vtable->destroy(storage);
  163|  3.62M|            this->vtable = nullptr;
  164|  3.62M|        }
  165|  5.21M|    }
_ZN4linb8any_castIdEET_RKNS_3anyE:
  468|  16.7k|{
  469|  16.7k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|  16.7k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|  16.7k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 16.7k]
  ------------------
  472|  16.7k|#endif
  473|  16.7k|    return *p;
  474|  16.7k|}
_ZN4linb8any_castIKdEEPKT_PKNS_3anyE:
  510|  16.7k|{
  511|  16.7k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|  16.7k|#ifndef ANY_IMPL_NO_RTTI
  514|  16.7k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 16.7k, False: 0]
  |  Branch (514:20): [True: 16.7k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|  16.7k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|  16.7k|}
_ZNK4linb3any8is_typedERKSt9type_info:
  355|   338k|    {
  356|   338k|        return is_same(this->type(), t);
  357|   338k|    }
_ZN4linb3any7is_sameERKSt9type_infoS3_:
  368|   338k|    {
  369|       |#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
  370|       |        return &a == &b;
  371|       |#else
  372|   338k|        return a == b;
  373|   338k|#endif
  374|   338k|    }
_ZNK4linb3any4castIKdEEPKT_v:
  380|  16.7k|    {
  381|  16.7k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 16.7k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|  16.7k|            reinterpret_cast<const T*>(&storage.stack);
  384|  16.7k|    }
_ZN4linb8any_castIN7SafeAny12SimpleStringEEET_RKNS_3anyE:
  468|  63.2k|{
  469|  63.2k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|  63.2k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|  63.2k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 63.2k]
  ------------------
  472|  63.2k|#endif
  473|  63.2k|    return *p;
  474|  63.2k|}
_ZN4linb8any_castIKN7SafeAny12SimpleStringEEEPKT_PKNS_3anyE:
  510|  63.2k|{
  511|  63.2k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|  63.2k|#ifndef ANY_IMPL_NO_RTTI
  514|  63.2k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 63.2k, False: 0]
  |  Branch (514:20): [True: 63.2k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|  63.2k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|  63.2k|}
_ZNK4linb3any4castIKN7SafeAny12SimpleStringEEEPKT_v:
  380|  63.2k|    {
  381|  63.2k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 63.2k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|  63.2k|            reinterpret_cast<const T*>(&storage.stack);
  384|  63.2k|    }
_ZN4linb8any_castIlEET_RKNS_3anyE:
  468|   258k|{
  469|   258k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|   258k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|   258k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 258k]
  ------------------
  472|   258k|#endif
  473|   258k|    return *p;
  474|   258k|}
_ZN4linb8any_castIKlEEPKT_PKNS_3anyE:
  510|   258k|{
  511|   258k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|   258k|#ifndef ANY_IMPL_NO_RTTI
  514|   258k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 258k, False: 0]
  |  Branch (514:20): [True: 258k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|   258k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|   258k|}
_ZNK4linb3any4castIKlEEPKT_v:
  380|   258k|    {
  381|   258k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 258k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|   258k|            reinterpret_cast<const T*>(&storage.stack);
  384|   258k|    }
_ZN4linb3anyC2IlvEEOT_:
  110|  1.38M|    {
  111|  1.38M|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|  1.38M|            "T shall satisfy the CopyConstructible requirements.");
  113|  1.38M|        this->construct(std::forward<ValueType>(value));
  114|  1.38M|    }
_ZN4linb3any9constructIlEEvOT_:
  439|  1.38M|    {
  440|  1.38M|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|  1.38M|        this->vtable = vtable_for_type<T>();
  443|       |
  444|  1.38M|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|  1.38M|    }
_ZN4linb3any15vtable_for_typeIlEEPNS0_11vtable_typeEv:
  333|  1.38M|    {
  334|  1.38M|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|  1.38M|        static vtable_type table = {
  336|  1.38M|#ifndef ANY_IMPL_NO_RTTI
  337|  1.38M|            VTableType::type,
  338|  1.38M|#endif
  339|  1.38M|            VTableType::destroy,
  340|  1.38M|            VTableType::copy, VTableType::move,
  341|  1.38M|            VTableType::swap,
  342|  1.38M|        };
  343|  1.38M|        return &table;
  344|  1.38M|    }
_ZN4linb3any12vtable_stackIlE4typeEv:
  289|  1.30M|        {
  290|  1.30M|            return typeid(T);
  291|  1.30M|        }
_ZN4linb3any12vtable_stackIlE7destroyERNS0_13storage_unionE:
  295|  4.77M|        {
  296|  4.77M|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|  4.77M|        }
_ZN4linb3any12vtable_stackIlE4copyERKNS0_13storage_unionERS3_:
  300|  1.64M|        {
  301|  1.64M|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|  1.64M|        }
_ZN4linb3any12vtable_stackIlE4moveERNS0_13storage_unionES4_:
  305|  1.74M|        {
  306|       |            // one of the conditions for using vtable_stack is a nothrow move constructor,
  307|       |            // so this move constructor will never throw a exception.
  308|  1.74M|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|  1.74M|            destroy(src);
  310|  1.74M|        }
_ZN4linb3any12vtable_stackIlE4swapERNS0_13storage_unionES4_:
  313|   118k|        {
  314|   118k|            storage_union tmp_storage;
  315|   118k|            move(rhs, tmp_storage);
  316|   118k|            move(lhs, rhs);
  317|   118k|            move(tmp_storage, lhs);
  318|   118k|        }
_ZN4linb3any12do_constructIllEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|  1.38M|    {
  432|  1.38M|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|  1.38M|    }
_ZN4linb3anyaSERKS0_:
  129|   167k|    {
  130|   167k|        any(rhs).swap(*this);
  131|   167k|        return *this;
  132|   167k|    }
_ZN4linb3anyC2ERKS0_:
   78|  1.98M|        vtable(rhs.vtable)
   79|  1.98M|    {
   80|  1.98M|        if(!rhs.empty())
  ------------------
  |  Branch (80:12): [True: 1.98M, False: 414]
  ------------------
   81|  1.98M|        {
   82|  1.98M|            rhs.vtable->copy(rhs.storage, this->storage);
   83|  1.98M|        }
   84|  1.98M|    }
_ZN4linb3any4swapERS0_:
  183|   209k|    {
  184|   209k|        if(this->vtable != rhs.vtable)
  ------------------
  |  Branch (184:12): [True: 37.1k, False: 172k]
  ------------------
  185|  37.1k|        {
  186|  37.1k|            any tmp(std::move(rhs));
  187|       |
  188|       |            // move from *this to rhs.
  189|  37.1k|            rhs.vtable = this->vtable;
  190|  37.1k|            if(this->vtable != nullptr)
  ------------------
  |  Branch (190:16): [True: 37.1k, False: 0]
  ------------------
  191|  37.1k|            {
  192|  37.1k|                this->vtable->move(this->storage, rhs.storage);
  193|       |                //this->vtable = nullptr; -- unneeded, see below
  194|  37.1k|            }
  195|       |
  196|       |            // move from tmp (previously rhs) to *this.
  197|  37.1k|            this->vtable = tmp.vtable;
  198|  37.1k|            if(tmp.vtable != nullptr)
  ------------------
  |  Branch (198:16): [True: 6.53k, False: 30.5k]
  ------------------
  199|  6.53k|            {
  200|  6.53k|                tmp.vtable->move(tmp.storage, this->storage);
  201|  6.53k|                tmp.vtable = nullptr;
  202|  6.53k|            }
  203|  37.1k|        }
  204|   172k|        else // same types
  205|   172k|        {
  206|   172k|            if(this->vtable != nullptr)
  ------------------
  |  Branch (206:16): [True: 140k, False: 31.6k]
  ------------------
  207|   140k|                this->vtable->swap(this->storage, rhs.storage);
  208|   172k|        }
  209|   209k|    }
_ZN4linb3anyC2EOS0_:
   89|  1.49M|        vtable(rhs.vtable)
   90|  1.49M|    {
   91|  1.49M|        if(!rhs.empty())
  ------------------
  |  Branch (91:12): [True: 1.46M, False: 30.5k]
  ------------------
   92|  1.46M|        {
   93|  1.46M|            rhs.vtable->move(rhs.storage, this->storage);
   94|  1.46M|            rhs.vtable = nullptr;
   95|  1.46M|        }
   96|  1.49M|    }
_ZN4linb3anyaSEOS0_:
  139|  40.5k|    {
  140|  40.5k|        std::move(rhs).swap(*this);
  141|  40.5k|        return *this;
  142|  40.5k|    }
_ZN4linb3anyaSIlvEERS0_OT_:
  150|    853|    {
  151|    853|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  152|    853|            "T shall satisfy the CopyConstructible requirements.");
  153|    853|        any(std::forward<ValueType>(value)).swap(*this);
  154|    853|        return *this;
  155|    853|    }
_ZN4linb3anyaSIdvEERS0_OT_:
  150|    196|    {
  151|    196|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  152|    196|            "T shall satisfy the CopyConstructible requirements.");
  153|    196|        any(std::forward<ValueType>(value)).swap(*this);
  154|    196|        return *this;
  155|    196|    }
_ZN4linb3anyC2IdvEEOT_:
  110|    196|    {
  111|    196|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|    196|            "T shall satisfy the CopyConstructible requirements.");
  113|    196|        this->construct(std::forward<ValueType>(value));
  114|    196|    }
_ZN4linb3any9constructIdEEvOT_:
  439|    196|    {
  440|    196|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|    196|        this->vtable = vtable_for_type<T>();
  443|       |
  444|    196|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|    196|    }
_ZN4linb3any15vtable_for_typeIdEEPNS0_11vtable_typeEv:
  333|   163k|    {
  334|   163k|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|   163k|        static vtable_type table = {
  336|   163k|#ifndef ANY_IMPL_NO_RTTI
  337|   163k|            VTableType::type,
  338|   163k|#endif
  339|   163k|            VTableType::destroy,
  340|   163k|            VTableType::copy, VTableType::move,
  341|   163k|            VTableType::swap,
  342|   163k|        };
  343|   163k|        return &table;
  344|   163k|    }
_ZN4linb3any12vtable_stackIdE4typeEv:
  289|   107k|        {
  290|   107k|            return typeid(T);
  291|   107k|        }
_ZN4linb3any12vtable_stackIdE7destroyERNS0_13storage_unionE:
  295|   208k|        {
  296|   208k|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|   208k|        }
_ZN4linb3any12vtable_stackIdE4copyERKNS0_13storage_unionERS3_:
  300|  19.6k|        {
  301|  19.6k|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|  19.6k|        }
_ZN4linb3any12vtable_stackIdE4moveERNS0_13storage_unionES4_:
  305|  25.5k|        {
  306|       |            // one of the conditions for using vtable_stack is a nothrow move constructor,
  307|       |            // so this move constructor will never throw a exception.
  308|  25.5k|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|  25.5k|            destroy(src);
  310|  25.5k|        }
_ZN4linb3any12vtable_stackIdE4swapERNS0_13storage_unionES4_:
  313|  3.11k|        {
  314|  3.11k|            storage_union tmp_storage;
  315|  3.11k|            move(rhs, tmp_storage);
  316|  3.11k|            move(lhs, rhs);
  317|  3.11k|            move(tmp_storage, lhs);
  318|  3.11k|        }
_ZN4linb3any12do_constructIddEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|    196|    {
  432|    196|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|    196|    }
_ZN4linb3anyC2IRKdvEEOT_:
  110|   162k|    {
  111|   162k|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|   162k|            "T shall satisfy the CopyConstructible requirements.");
  113|   162k|        this->construct(std::forward<ValueType>(value));
  114|   162k|    }
_ZN4linb3any9constructIRKdEEvOT_:
  439|   162k|    {
  440|   162k|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|   162k|        this->vtable = vtable_for_type<T>();
  443|       |
  444|   162k|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|   162k|    }
_ZN4linb3any12do_constructIRKddEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|   162k|    {
  432|   162k|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|   162k|    }
_ZN4linb3anyC2IN7SafeAny12SimpleStringEvEEOT_:
  110|   101k|    {
  111|   101k|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|   101k|            "T shall satisfy the CopyConstructible requirements.");
  113|   101k|        this->construct(std::forward<ValueType>(value));
  114|   101k|    }
_ZN4linb3any9constructIN7SafeAny12SimpleStringEEEvOT_:
  439|   101k|    {
  440|   101k|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|   101k|        this->vtable = vtable_for_type<T>();
  443|       |
  444|   101k|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|   101k|    }
_ZN4linb3any15vtable_for_typeIN7SafeAny12SimpleStringEEEPNS0_11vtable_typeEv:
  333|   101k|    {
  334|   101k|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|   101k|        static vtable_type table = {
  336|   101k|#ifndef ANY_IMPL_NO_RTTI
  337|   101k|            VTableType::type,
  338|   101k|#endif
  339|   101k|            VTableType::destroy,
  340|   101k|            VTableType::copy, VTableType::move,
  341|   101k|            VTableType::swap,
  342|   101k|        };
  343|   101k|        return &table;
  344|   101k|    }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4typeEv:
  289|   380k|        {
  290|   380k|            return typeid(T);
  291|   380k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE7destroyERNS0_13storage_unionE:
  295|   578k|        {
  296|   578k|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|   578k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4copyERKNS0_13storage_unionERS5_:
  300|   321k|        {
  301|   321k|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|   321k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4moveERNS0_13storage_unionES6_:
  305|   155k|        {
  306|       |            // one of the conditions for using vtable_stack is a nothrow move constructor,
  307|       |            // so this move constructor will never throw a exception.
  308|   155k|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|   155k|            destroy(src);
  310|   155k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4swapERNS0_13storage_unionES6_:
  313|  18.3k|        {
  314|  18.3k|            storage_union tmp_storage;
  315|  18.3k|            move(rhs, tmp_storage);
  316|  18.3k|            move(lhs, rhs);
  317|  18.3k|            move(tmp_storage, lhs);
  318|  18.3k|        }
_ZN4linb3any12do_constructIN7SafeAny12SimpleStringES3_EENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|   101k|    {
  432|   101k|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|   101k|    }

_ZNK6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  5.25k|    {
 2192|  5.25k|        return has_value();
 2193|  5.25k|    }
_ZNK6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  10.5k|    {
 2197|  10.5k|        return contained.has_value();
 2198|  10.5k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  10.5k|    {
  787|  10.5k|        return m_has_value;
  788|  10.5k|    }
_ZNK6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  6.56k|    {
 2192|  6.56k|        return has_value();
 2193|  6.56k|    }
_ZNK6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  17.0k|    {
 2197|  17.0k|        return contained.has_value();
 2198|  17.0k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  17.0k|    {
  787|  17.0k|        return m_has_value;
  788|  17.0k|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IdTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIdOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_dEE5valueEiE4typeELi0EEESC_:
 1927|   527k|    : contained( true )
 1928|   527k|    {
 1929|   527k|        contained.construct_value( std::forward<U>( value ) );
 1930|   527k|    }
_ZN6nonstd13expected_lite6detail9storage_tIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|   535k|        : storage_t_impl<T, E>( has_value )
  922|   535k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|   536k|        : m_has_value( has_value )
  674|   536k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOd:
  687|   527k|    {
  688|   527k|        new( &m_value ) value_type( std::move( e ) );
  689|   527k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRA39_KcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS7_:
 1566|    178|{
 1567|    178|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|    178|}
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IRA39_S2_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS9_E4typeESt10in_place_tEE5valuentsr3std7is_sameISD_S4_EE5valueEiE4typeELi0EEEOS9_:
 1237|    178|    : m_error( std::forward<E2>( error ) )
 1238|    178|    {}
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS7_OT_EE5valuesr3std14is_convertibleISE_S7_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISD_EE:
 1977|    178|    : contained( false )
 1978|    178|    {
 1979|    178|        contained.construct_error( std::move( error.error() ) );
 1980|    178|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOS8_:
  714|    356|    {
  715|    356|        new( &m_error ) error_type( std::move( e ) );
  716|    356|    }
_ZNR6nonstd13expected_lite15unexpected_typeIPKcE5errorEv:
 1334|  5.05k|    {
 1335|  5.05k|        return m_error;
 1336|  5.05k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|   536k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IRdTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIdOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISC_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SH_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESH_EE5valuesr3std14is_convertibleISD_dEE5valueEiE4typeELi0EEESD_:
 1927|  7.86k|    : contained( true )
 1928|  7.86k|    {
 1929|  7.86k|        contained.construct_value( std::forward<U>( value ) );
 1930|  7.86k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueERKd:
  682|  7.86k|    {
  683|  7.86k|        new( &m_value ) value_type( e );
  684|  7.86k|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2EOS8_:
 1793|    178|    nsel_constexpr14 expected( expected &&      ) = default;
_ZN6nonstd13expected_lite6detail9storage_tIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2EOS9_:
  932|    178|        : storage_t_impl<T, E>( other.has_value() )
  933|    178|    {
  934|    178|        if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
  ------------------
  |  Branch (934:14): [True: 0, False: 178]
  ------------------
  935|    178|        else                     this->construct_error( std::move( other.error() ) );
  936|    178|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  1.60M|    {
  787|  1.60M|        return m_has_value;
  788|  1.60M|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|   535k|    {
  742|   535k|        return m_value;
  743|   535k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
  771|    356|    {
  772|    356|        return m_error;
  773|    356|    }
_ZNR6nonstd13expected_lite15unexpected_typeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 1334|  1.31k|    {
 1335|  1.31k|        return m_error;
 1336|  1.31k|    }
_ZNK6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|   536k|    {
 2192|   536k|        return has_value();
 2193|   536k|    }
_ZNK6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  1.60M|    {
 2197|  1.60M|        return contained.has_value();
 2198|  1.60M|    }
_ZNR6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|   535k|    {
 2211|   535k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 535k, False: 0]
  ------------------
 2212|   535k|            ? ( contained.value() )
 2213|   535k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|   535k|    }
_ZNR6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 2241|    178|    {
 2242|       |        return assert( ! has_value() ), contained.error();
 2243|    178|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|   536k|    {
 2038|   536k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 535k, False: 356]
  ------------------
 2039|    356|        else               contained.destruct_error();
 2040|   536k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|   535k|    {
  705|   535k|        m_value.~value_type();
  706|   535k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|    356|    {
  732|    356|        m_error.~error_type();
  733|    356|    }
_ZN6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IlTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIlOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_lEE5valueEiE4typeELi0EEESC_:
 1927|  5.67k|    : contained( true )
 1928|  5.67k|    {
 1929|  5.67k|        contained.construct_value( std::forward<U>( value ) );
 1930|  5.67k|    }
_ZN6nonstd13expected_lite6detail9storage_tIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.67k|        : storage_t_impl<T, E>( has_value )
  922|  5.67k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.67k|        : m_has_value( has_value )
  674|  5.67k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOl:
  687|  5.67k|    {
  688|  5.67k|        new( &m_value ) value_type( std::move( e ) );
  689|  5.67k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.67k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  17.0k|    {
  787|  17.0k|        return m_has_value;
  788|  17.0k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  5.67k|    {
  742|  5.67k|        return m_value;
  743|  5.67k|    }
_ZNK6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  5.67k|    {
 2192|  5.67k|        return has_value();
 2193|  5.67k|    }
_ZNK6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  17.0k|    {
 2197|  17.0k|        return contained.has_value();
 2198|  17.0k|    }
_ZNR6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  5.67k|    {
 2211|  5.67k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 5.67k, False: 0]
  ------------------
 2212|  5.67k|            ? ( contained.value() )
 2213|  5.67k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  5.67k|    }
_ZN6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.67k|    {
 2038|  5.67k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 5.67k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  5.67k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  5.67k|    {
  705|  5.67k|        m_value.~value_type();
  706|  5.67k|    }
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.25k|    {
 2038|  5.25k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 3.94k, False: 1.31k]
  ------------------
 2039|  1.31k|        else               contained.destruct_error();
 2040|  5.25k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  3.94k|    {
  705|  3.94k|        m_value.~value_type();
  706|  3.94k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  1.31k|    {
  732|  1.31k|        m_error.~error_type();
  733|  1.31k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.25k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  6.56k|    {
 2038|  6.56k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 3.94k, False: 2.62k]
  ------------------
 2039|  2.62k|        else               contained.destruct_error();
 2040|  6.56k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  3.94k|    {
  705|  3.94k|        m_value.~value_type();
  706|  3.94k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  2.62k|    {
  732|  2.62k|        m_error.~error_type();
  733|  2.62k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  6.56k|    ~storage_t_impl() {}
_ZNR6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  3.94k|    {
 2211|  3.94k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 3.94k, False: 0]
  ------------------
 2212|  3.94k|            ? ( contained.value() )
 2213|  3.94k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  3.94k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  3.94k|    {
  742|  3.94k|        return m_value;
  743|  3.94k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
  771|  1.31k|    {
  772|  1.31k|        return m_error;
  773|  1.31k|    }
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS3_TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS3_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISD_E4typeESt10in_place_tEE5valuentsr3std7is_sameISA_SI_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS9_EESI_EE5valuesr3std14is_convertibleISE_S3_EE5valueEiE4typeELi0EEESE_:
 1927|  2.77k|    : contained( true )
 1928|  2.77k|    {
 1929|  2.77k|        contained.construct_value( std::forward<U>( value ) );
 1930|  2.77k|    }
_ZN6nonstd13expected_lite6detail9storage_tIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.03k|        : storage_t_impl<T, E>( has_value )
  922|  5.03k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.03k|        : m_has_value( has_value )
  674|  5.03k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOS4_:
  687|  2.77k|    {
  688|  2.77k|        new( &m_value ) value_type( std::move( e ) );
  689|  2.77k|    }
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS9_TnNSt9enable_ifIXaasr3std16is_constructibleIS9_OT_EE5valuesr3std14is_convertibleISE_S9_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISD_EE:
 1977|  1.31k|    : contained( false )
 1978|  1.31k|    {
 1979|  1.31k|        contained.construct_error( std::move( error.error() ) );
 1980|  1.31k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOSA_:
  714|  2.25k|    {
  715|  2.25k|        new( &m_error ) error_type( std::move( e ) );
  716|  2.25k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.03k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  5.03k|    {
  787|  5.03k|        return m_has_value;
  788|  5.03k|    }
_ZNK6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  5.03k|    {
 2197|  5.03k|        return contained.has_value();
 2198|  5.03k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOSB_:
 1566|  1.31k|{
 1567|  1.31k|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|  1.31k|}
_ZN6nonstd13expected_lite15unexpected_typeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IRS7_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS7_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISC_E4typeESt10in_place_tEE5valuentsr3std7is_sameISG_S8_EE5valueEiE4typeELi0EEEOSC_:
 1237|  1.31k|    : m_error( std::forward<E2>( error ) )
 1238|  1.31k|    {}
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.03k|    {
 2038|  5.03k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 2.77k, False: 2.25k]
  ------------------
 2039|  2.25k|        else               contained.destruct_error();
 2040|  5.03k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  2.77k|    {
  705|  2.77k|        m_value.~value_type();
  706|  2.77k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  2.25k|    {
  732|  2.25k|        m_error.~error_type();
  733|  2.25k|    }
_ZNK6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_E9has_valueEv:
 2196|   246k|    {
 2197|   246k|        return contained.has_value();
 2198|   246k|    }
_ZNK6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_EcvbEv:
 2191|  82.2k|    {
 2192|  82.2k|        return has_value();
 2193|  82.2k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E9has_valueEv:
  786|   246k|    {
  787|   246k|        return m_has_value;
  788|   246k|    }
_ZN6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_EC2IS7_TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS7_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_S7_EE5valueEiE4typeELi0EEESC_:
 1927|  82.2k|    : contained( true )
 1928|  82.2k|    {
 1929|  82.2k|        contained.construct_value( std::forward<U>( value ) );
 1930|  82.2k|    }
_ZN6nonstd13expected_lite6detail9storage_tINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_Lb1ELb1EEC2Eb:
  921|  82.2k|        : storage_t_impl<T, E>( has_value )
  922|  82.2k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_EC2Eb:
  673|  82.2k|        : m_has_value( has_value )
  674|  82.2k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E15construct_valueEOS8_:
  687|  82.2k|    {
  688|  82.2k|        new( &m_value ) value_type( std::move( e ) );
  689|  82.2k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_ED2Ev:
  670|  82.2k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite15make_unexpectedIPKcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS6_:
 1566|  4.81k|{
 1567|  4.81k|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|  4.81k|}
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEv:
  677|  3.94k|    {
  678|  3.94k|        new( &m_value ) value_type();
  679|  3.94k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOS9_:
  714|  1.31k|    {
  715|  1.31k|        new( &m_error ) error_type( std::move( e ) );
  716|  1.31k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E5valueEv:
  741|  82.2k|    {
  742|  82.2k|        return m_value;
  743|  82.2k|    }
_ZNR6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_E5valueEv:
 2210|  82.2k|    {
 2211|  82.2k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 82.2k, False: 0]
  ------------------
 2212|  82.2k|            ? ( contained.value() )
 2213|  82.2k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  82.2k|    }
_ZN6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_ED2Ev:
 2037|  82.2k|    {
 2038|  82.2k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 82.2k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  82.2k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E14destruct_valueEv:
  704|  82.2k|    {
  705|  82.2k|        m_value.~value_type();
  706|  82.2k|    }
_ZN6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS3_TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS3_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISD_E4typeESt10in_place_tEE5valuentsr3std7is_sameISA_SI_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS9_EESI_EE5valuesr3std14is_convertibleISE_S3_EE5valueEiE4typeELi0EEESE_:
 1927|  17.4k|    : contained( true )
 1928|  17.4k|    {
 1929|  17.4k|        contained.construct_value( std::forward<U>( value ) );
 1930|  17.4k|    }
_ZN6nonstd13expected_lite6detail9storage_tIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  17.4k|        : storage_t_impl<T, E>( has_value )
  922|  17.4k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  17.4k|        : m_has_value( has_value )
  674|  17.4k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOS4_:
  687|  17.4k|    {
  688|  17.4k|        new( &m_value ) value_type( std::move( e ) );
  689|  17.4k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  17.4k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  52.3k|    {
  787|  52.3k|        return m_has_value;
  788|  52.3k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  17.4k|    {
  742|  17.4k|        return m_value;
  743|  17.4k|    }
_ZNK6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  17.4k|    {
 2192|  17.4k|        return has_value();
 2193|  17.4k|    }
_ZNK6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  52.3k|    {
 2197|  52.3k|        return contained.has_value();
 2198|  52.3k|    }
_ZNR6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  17.4k|    {
 2211|  17.4k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 17.4k, False: 0]
  ------------------
 2212|  17.4k|            ? ( contained.value() )
 2213|  17.4k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  17.4k|    }
_ZN6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  17.4k|    {
 2038|  17.4k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 17.4k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  17.4k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  17.4k|    {
  705|  17.4k|        m_value.~value_type();
  706|  17.4k|    }
_ZN6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IbTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIbOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_bEE5valueEiE4typeELi0EEESC_:
 1927|  4.86k|    : contained( true )
 1928|  4.86k|    {
 1929|  4.86k|        contained.construct_value( std::forward<U>( value ) );
 1930|  4.86k|    }
_ZN6nonstd13expected_lite6detail9storage_tIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  4.86k|        : storage_t_impl<T, E>( has_value )
  922|  4.86k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  4.86k|        : m_has_value( has_value )
  674|  4.86k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOb:
  687|  4.86k|    {
  688|  4.86k|        new( &m_value ) value_type( std::move( e ) );
  689|  4.86k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  4.86k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  14.5k|    {
  787|  14.5k|        return m_has_value;
  788|  14.5k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  4.86k|    {
  742|  4.86k|        return m_value;
  743|  4.86k|    }
_ZNK6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  4.86k|    {
 2192|  4.86k|        return has_value();
 2193|  4.86k|    }
_ZNK6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  14.5k|    {
 2197|  14.5k|        return contained.has_value();
 2198|  14.5k|    }
_ZNR6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  4.86k|    {
 2211|  4.86k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 4.86k, False: 0]
  ------------------
 2212|  4.86k|            ? ( contained.value() )
 2213|  4.86k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  4.86k|    }
_ZN6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  4.86k|    {
 2038|  4.86k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 4.86k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  4.86k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  4.86k|    {
  705|  4.86k|        m_value.~value_type();
  706|  4.86k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRA13_KcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS7_:
 1566|     69|{
 1567|     69|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|     69|}
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IRA13_S2_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS9_E4typeESt10in_place_tEE5valuentsr3std7is_sameISD_S4_EE5valueEiE4typeELi0EEEOS9_:
 1237|     69|    : m_error( std::forward<E2>( error ) )
 1238|     69|    {}
_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleISF_OT_EE5valuesr3std14is_convertibleISM_SF_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISL_EE:
 1977|  2.62k|    : contained( false )
 1978|  2.62k|    {
 1979|  2.62k|        contained.construct_error( std::move( error.error() ) );
 1980|  2.62k|    }
_ZN6nonstd13expected_lite6detail9storage_tISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  6.56k|        : storage_t_impl<T, E>( has_value )
  922|  6.56k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  6.56k|        : m_has_value( has_value )
  674|  6.56k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOSG_:
  714|  2.62k|    {
  715|  2.62k|        new( &m_error ) error_type( std::move( e ) );
  716|  2.62k|    }
script_parser.cpp:_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IZNS3_11ParseScriptERKSF_E3$_0TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS9_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISM_E4typeESt10in_place_tEE5valuentsr3std7is_sameISG_SR_EE5valuentsr3std7is_sameINS0_15unexpected_typeISF_EESR_EE5valuesr3std14is_convertibleISN_S9_EE5valueEiE4typeELi0EEESN_:
 1927|  3.94k|    : contained( true )
 1928|  3.94k|    {
 1929|  3.94k|        contained.construct_value( std::forward<U>( value ) );
 1930|  3.94k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOSA_:
  687|  3.94k|    {
  688|  3.94k|        new( &m_value ) value_type( std::move( e ) );
  689|  3.94k|    }
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IS3_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS7_E4typeESt10in_place_tEE5valuentsr3std7is_sameISB_S4_EE5valueEiE4typeELi0EEEOS7_:
 1237|  4.81k|    : m_error( std::forward<E2>( error ) )
 1238|  4.81k|    {}
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS9_OT_EE5valuesr3std14is_convertibleISG_S9_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISF_EE:
 1977|    943|    : contained( false )
 1978|    943|    {
 1979|    943|        contained.construct_error( std::move( error.error() ) );
 1980|    943|    }
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS8_OT_EE5valuesr3std14is_convertibleISF_S8_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISE_EE:
 1977|  1.31k|    : contained( false )
 1978|  1.31k|    {
 1979|  1.31k|        contained.construct_error( std::move( error.error() ) );
 1980|  1.31k|    }
_ZN6nonstd13expected_lite6detail9storage_tISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.25k|        : storage_t_impl<T, E>( has_value )
  922|  5.25k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.25k|        : m_has_value( has_value )
  674|  5.25k|    {}
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2ILb1ETnNSt9enable_ifIXT_EiE4typeELi0EEEv:
 1787|  3.94k|    : contained( true )
 1788|  3.94k|    {
 1789|  3.94k|        contained.construct_value();
 1790|  3.94k|    }
_ZNR6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 2241|  1.31k|    {
 2242|       |        return assert( ! has_value() ), contained.error();
 2243|  1.31k|    }

_ZN2BT21BehaviorTreeExceptionC2IJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEDpRKT_:
   33|  5.52k|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|  5.52k|  {}
_ZNK2BT21BehaviorTreeException4whatEv:
   37|  5.75k|  {
   38|  5.75k|    return message_.c_str();
   39|  5.75k|  }
_ZN2BT12RuntimeErrorC2IJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEDpRKT_:
   67|  5.52k|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|  5.52k|  {}
_ZN2BT12RuntimeErrorC2IJA42_cEEEDpRKT_:
   67|      3|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      3|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA42_cEEEDpRKT_:
   33|      3|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      3|  {}
_ZN2BT12RuntimeErrorC2IJA33_cEEEDpRKT_:
   67|      3|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      3|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA33_cEEEDpRKT_:
   33|      3|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      3|  {}
_ZN2BT12RuntimeErrorC2IJA31_cEEEDpRKT_:
   67|      1|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      1|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA31_cEEEDpRKT_:
   33|      1|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      1|  {}
_ZN2BT12RuntimeErrorC2IJA47_cEEEDpRKT_:
   67|     38|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|     38|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA47_cEEEDpRKT_:
   33|     38|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|     38|  {}
_ZN2BT12RuntimeErrorC2IJA63_cEEEDpRKT_:
   67|      6|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      6|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA63_cEEEDpRKT_:
   33|      6|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      6|  {}
_ZN2BT12RuntimeErrorC2IJA35_cEEEDpRKT_:
   67|      4|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      4|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA35_cEEEDpRKT_:
   33|      4|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      4|  {}
_ZN2BT12RuntimeErrorC2IJA74_cEEEDpRKT_:
   67|      7|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      7|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA74_cEEEDpRKT_:
   33|      7|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      7|  {}
_ZN2BT12RuntimeErrorC2IJA79_cEEEDpRKT_:
   67|    137|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|    137|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA79_cEEEDpRKT_:
   33|    137|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|    137|  {}
_ZN2BT12RuntimeErrorC2IJA24_cEEEDpRKT_:
   67|     27|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|     27|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA24_cEEEDpRKT_:
   33|     27|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|     27|  {}

_ZN2BT3Ast19ExprUnaryArithmeticC2ENS1_4op_tESt10shared_ptrINS0_8ExprBaseEE:
  118|  14.5k|  explicit ExprUnaryArithmetic(op_t op, expr_ptr e) : op(op), rhs(std::move(e))
  119|  14.5k|  {}
_ZN2BT3Ast8ExprBaseD2Ev:
   57|  6.58M|  virtual ~ExprBase() = default;
_ZNK2BT3Ast19ExprUnaryArithmetic8evaluateERNS0_11EnvironmentE:
  122|  4.12k|  {
  123|  4.12k|    auto rhs_v = rhs->evaluate(env);
  124|  4.12k|    if(rhs_v.isNumber())
  ------------------
  |  Branch (124:8): [True: 4.04k, False: 74]
  ------------------
  125|  4.04k|    {
  126|  4.04k|      const double rv = rhs_v.cast<double>();
  127|  4.04k|      switch(op)
  ------------------
  |  Branch (127:14): [True: 4.03k, False: 11]
  ------------------
  128|  4.04k|      {
  129|  1.41k|        case negate:
  ------------------
  |  Branch (129:9): [True: 1.41k, False: 2.62k]
  ------------------
  130|  1.41k|          return Any(-rv);
  131|    952|        case complement:
  ------------------
  |  Branch (131:9): [True: 952, False: 3.09k]
  ------------------
  132|    952|          if(rv > static_cast<double>(std::numeric_limits<int64_t>::max()) ||
  ------------------
  |  Branch (132:14): [True: 2, False: 950]
  ------------------
  133|    950|             rv < static_cast<double>(std::numeric_limits<int64_t>::min()))
  ------------------
  |  Branch (133:14): [True: 1, False: 949]
  ------------------
  134|      3|          {
  135|      3|            throw RuntimeError("Number out of range for bitwise operation");
  136|      3|          }
  137|    949|          return Any(static_cast<double>(~static_cast<int64_t>(rv)));
  138|  1.66k|        case logical_not:
  ------------------
  |  Branch (138:9): [True: 1.66k, False: 2.38k]
  ------------------
  139|  1.66k|          return Any(static_cast<double>(!static_cast<bool>(rv)));
  140|  4.04k|      }
  141|  4.04k|    }
  142|     74|    else if(rhs_v.isString())
  ------------------
  |  Branch (142:13): [True: 3, False: 71]
  ------------------
  143|      3|    {
  144|      3|      throw RuntimeError("Invalid operator for std::string");
  145|      3|    }
  146|     71|    throw RuntimeError("ExprUnaryArithmetic: undefined");
  147|  4.12k|  }
_ZN2BT3Ast11ExprLiteralC2ENS_3AnyE:
   71|  1.45M|  ExprLiteral(Any v) : value(v)
   72|  1.45M|  {}
_ZNK2BT3Ast11ExprLiteral8evaluateERNS0_11EnvironmentE:
   75|   162k|  {
   76|   162k|    return value;
   77|   162k|  }
_ZN2BT3Ast8ExprNameC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   84|  4.92M|  explicit ExprName(std::string n) : name(std::move(n))
   85|  4.92M|  {}
_ZNK2BT3Ast8ExprName8evaluateERNS0_11EnvironmentE:
   88|   171k|  {
   89|       |    //search first in the enums table
   90|   171k|    if(env.enums)
  ------------------
  |  Branch (90:8): [True: 171k, False: 0]
  ------------------
   91|   171k|    {
   92|   171k|      auto enum_ptr = env.enums->find(name);
   93|   171k|      if(enum_ptr != env.enums->end())
  ------------------
  |  Branch (93:10): [True: 0, False: 171k]
  ------------------
   94|      0|      {
   95|      0|        return Any(double(enum_ptr->second));
   96|      0|      }
   97|   171k|    }
   98|       |    // search now in the variables table
   99|   171k|    auto any_ref = env.vars->getAnyLocked(name);
  100|   171k|    if(!any_ref)
  ------------------
  |  Branch (100:8): [True: 518, False: 171k]
  ------------------
  101|    518|    {
  102|    518|      throw RuntimeError(StrCat("Variable not found: ", name));
  103|    518|    }
  104|   171k|    return *any_ref.get();
  105|   171k|  }
_ZN2BT3Ast14ExprAssignmentC2ESt10shared_ptrINS0_8ExprBaseEENS1_4op_tES4_:
  507|  63.7k|    : op(op), lhs(std::move(_lhs)), rhs(std::move(_rhs))
  508|  63.7k|  {}
_ZNK2BT3Ast14ExprAssignment8evaluateERNS0_11EnvironmentE:
  511|  25.8k|  {
  512|  25.8k|    auto varname = dynamic_cast<ExprName*>(lhs.get());
  513|  25.8k|    if(!varname)
  ------------------
  |  Branch (513:8): [True: 38, False: 25.7k]
  ------------------
  514|     38|    {
  515|     38|      throw RuntimeError("Assignment left operand not a blackboard entry");
  516|     38|    }
  517|  25.7k|    const auto& key = varname->name;
  518|       |
  519|  25.7k|    auto entry = env.vars->getEntry(key);
  520|  25.7k|    if(!entry)
  ------------------
  |  Branch (520:8): [True: 9.98k, False: 15.7k]
  ------------------
  521|  9.98k|    {
  522|       |      // variable doesn't exist, create it if using operator assign_create
  523|  9.98k|      if(op == assign_create)
  ------------------
  |  Branch (523:10): [True: 9.91k, False: 71]
  ------------------
  524|  9.91k|      {
  525|  9.91k|        env.vars->createEntry(key, PortInfo());
  526|  9.91k|        entry = env.vars->getEntry(key);
  527|  9.91k|        if(!entry)
  ------------------
  |  Branch (527:12): [True: 0, False: 9.91k]
  ------------------
  528|      0|        {
  529|      0|          throw LogicError("Bug: report");
  530|      0|        }
  531|  9.91k|      }
  532|     71|      else
  533|     71|      {
  534|       |        // fail otherwise
  535|     71|        auto msg = StrCat("The blackboard entry [", key,
  536|     71|                          "] doesn't exist, yet.\n"
  537|     71|                          "If you want to create a new one, "
  538|     71|                          "use the operator "
  539|     71|                          "[:=] instead of [=]");
  540|     71|        throw RuntimeError(msg);
  541|     71|      }
  542|  9.98k|    }
  543|  25.6k|    auto value = rhs->evaluate(env);
  544|       |
  545|  25.6k|    std::scoped_lock lock(entry->entry_mutex);
  546|  25.6k|    auto* dst_ptr = &entry->value;
  547|       |
  548|  25.6k|    auto errorPrefix = [dst_ptr, &key]() {
  549|  25.6k|      return StrCat("Error assigning a value to entry [", key, "] with type [",
  550|  25.6k|                    BT::demangle(dst_ptr->type()), "]. ");
  551|  25.6k|    };
  552|       |
  553|  25.6k|    if(value.empty())
  ------------------
  |  Branch (553:8): [True: 41, False: 25.6k]
  ------------------
  554|     41|    {
  555|     41|      throw RuntimeError(ErrorNotInit("right", opStr()));
  556|     41|    }
  557|       |
  558|  25.6k|    if(op == assign_create || op == assign_existing)
  ------------------
  |  Branch (558:8): [True: 15.6k, False: 10.0k]
  |  Branch (558:31): [True: 1.90k, False: 8.12k]
  ------------------
  559|  11.7k|    {
  560|       |      // the very fist assignment can come from any type.
  561|       |      // In the future, type check will be done by Any::copyInto
  562|  11.7k|      if(dst_ptr->empty() && entry->info.type() == typeid(AnyTypeAllowed))
  ------------------
  |  Branch (562:10): [True: 8.85k, False: 2.84k]
  |  Branch (562:10): [True: 8.85k, False: 2.84k]
  |  Branch (562:30): [True: 8.85k, False: 0]
  ------------------
  563|  8.85k|      {
  564|  8.85k|        *dst_ptr = value;
  565|  8.85k|      }
  566|  2.84k|      else if(value.isString() && !dst_ptr->isString())
  ------------------
  |  Branch (566:15): [True: 1.96k, False: 880]
  |  Branch (566:35): [True: 828, False: 1.13k]
  ------------------
  567|    828|      {
  568|       |        // special case: string to other type.
  569|       |        // Check if we can use the StringConverter
  570|    828|        auto const str = value.cast<std::string>();
  571|    828|        const auto* entry_info = env.vars->entryInfo(key);
  572|       |
  573|    828|        if(auto converter = entry_info->converter())
  ------------------
  |  Branch (573:17): [True: 0, False: 828]
  ------------------
  574|      0|        {
  575|      0|          *dst_ptr = converter(str);
  576|      0|        }
  577|    828|        else if(dst_ptr->isNumber())
  ------------------
  |  Branch (577:17): [True: 828, False: 0]
  ------------------
  578|    828|        {
  579|    828|          auto num_value = StringToDouble(value, env);
  580|    828|          *dst_ptr = Any(num_value);
  581|    828|        }
  582|      0|        else
  583|      0|        {
  584|      0|          auto msg = StrCat(errorPrefix(),
  585|      0|                            "\nThe right operand is a string, "
  586|      0|                            "can't convert to ",
  587|      0|                            demangle(dst_ptr->type()));
  588|      0|          throw RuntimeError(msg);
  589|      0|        }
  590|    828|      }
  591|  2.01k|      else
  592|  2.01k|      {
  593|  2.01k|        try
  594|  2.01k|        {
  595|  2.01k|          value.copyInto(*dst_ptr);
  596|  2.01k|        }
  597|  2.01k|        catch(std::exception&)
  598|  2.01k|        {
  599|     55|          auto msg = StrCat(errorPrefix(), "\nThe right operand has type [",
  600|     55|                            BT::demangle(value.type()), "] and can't be converted to [",
  601|     55|                            BT::demangle(dst_ptr->type()), "]");
  602|     55|          throw RuntimeError(msg);
  603|     55|        }
  604|  2.01k|      }
  605|  11.6k|      entry->sequence_id++;
  606|  11.6k|      entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  607|  11.6k|      return *dst_ptr;
  608|  11.7k|    }
  609|       |
  610|  13.9k|    if(dst_ptr->empty())
  ------------------
  |  Branch (610:8): [True: 5, False: 13.9k]
  ------------------
  611|      5|    {
  612|      5|      throw RuntimeError(ErrorNotInit("left", opStr()));
  613|      5|    }
  614|       |
  615|       |    // temporary use
  616|  13.9k|    Any temp_variable = *dst_ptr;
  617|       |
  618|  13.9k|    if(value.isNumber())
  ------------------
  |  Branch (618:8): [True: 1.73k, False: 12.2k]
  ------------------
  619|  1.73k|    {
  620|  1.73k|      if(!temp_variable.isNumber())
  ------------------
  |  Branch (620:10): [True: 6, False: 1.72k]
  ------------------
  621|      6|      {
  622|      6|        throw RuntimeError("This Assignment operator can't be used "
  623|      6|                           "with a non-numeric type");
  624|      6|      }
  625|       |
  626|  1.72k|      auto lv = temp_variable.cast<double>();
  627|  1.72k|      auto rv = value.cast<double>();
  628|  1.72k|      switch(op)
  629|  1.72k|      {
  630|    455|        case assign_plus:
  ------------------
  |  Branch (630:9): [True: 455, False: 1.27k]
  ------------------
  631|    455|          temp_variable = Any(lv + rv);
  632|    455|          break;
  633|    445|        case assign_minus:
  ------------------
  |  Branch (633:9): [True: 445, False: 1.28k]
  ------------------
  634|    445|          temp_variable = Any(lv - rv);
  635|    445|          break;
  636|    415|        case assign_times:
  ------------------
  |  Branch (636:9): [True: 415, False: 1.31k]
  ------------------
  637|    415|          temp_variable = Any(lv * rv);
  638|    415|          break;
  639|    412|        case assign_div:
  ------------------
  |  Branch (639:9): [True: 412, False: 1.31k]
  ------------------
  640|    412|          temp_variable = Any(lv / rv);
  641|    412|          break;
  642|      0|        default: {
  ------------------
  |  Branch (642:9): [True: 0, False: 1.72k]
  ------------------
  643|      0|        }
  644|  1.72k|      }
  645|  1.72k|    }
  646|  12.2k|    else if(value.isString())
  ------------------
  |  Branch (646:13): [True: 6.38k, False: 5.83k]
  ------------------
  647|  6.38k|    {
  648|  6.38k|      if(op == assign_plus)
  ------------------
  |  Branch (648:10): [True: 6.37k, False: 4]
  ------------------
  649|  6.37k|      {
  650|  6.37k|        auto lv = temp_variable.cast<std::string>();
  651|  6.37k|        auto rv = value.cast<std::string>();
  652|  6.37k|        temp_variable = Any(lv + rv);
  653|  6.37k|      }
  654|      4|      else
  655|      4|      {
  656|      4|        throw RuntimeError("Operator not supported for strings");
  657|      4|      }
  658|  6.38k|    }
  659|       |
  660|  13.9k|    temp_variable.copyInto(*dst_ptr);
  661|  13.9k|    entry->sequence_id++;
  662|  13.9k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  663|  13.9k|    return *dst_ptr;
  664|  13.9k|  }
_ZN2BT3Ast12ErrorNotInitB5cxx11EPKcS2_:
   62|     73|{
   63|     73|  return StrCat("The ", side, " operand of the operator [", op_str,
   64|     73|                "] is not initialized");
   65|     73|}
_ZNK2BT3Ast14ExprAssignment5opStrEv:
  485|     46|  {
  486|     46|    switch(op)
  ------------------
  |  Branch (486:12): [True: 46, False: 0]
  ------------------
  487|     46|    {
  488|     26|      case assign_create:
  ------------------
  |  Branch (488:7): [True: 26, False: 20]
  ------------------
  489|     26|        return ":=";
  490|     15|      case assign_existing:
  ------------------
  |  Branch (490:7): [True: 15, False: 31]
  ------------------
  491|     15|        return "=";
  492|      2|      case assign_plus:
  ------------------
  |  Branch (492:7): [True: 2, False: 44]
  ------------------
  493|      2|        return "+=";
  494|      1|      case assign_minus:
  ------------------
  |  Branch (494:7): [True: 1, False: 45]
  ------------------
  495|      1|        return "-=";
  496|      1|      case assign_times:
  ------------------
  |  Branch (496:7): [True: 1, False: 45]
  ------------------
  497|      1|        return "*=";
  498|      1|      case assign_div:
  ------------------
  |  Branch (498:7): [True: 1, False: 45]
  ------------------
  499|      1|        return "/=";
  500|     46|    }
  501|      0|    return "";
  502|     46|  }
_ZN2BT3Ast14StringToDoubleERKNS_3AnyERKNS0_11EnvironmentE:
   32|  8.42k|{
   33|  8.42k|  const auto str = value.cast<std::string>();
   34|  8.42k|  if(str == "true")
  ------------------
  |  Branch (34:6): [True: 196, False: 8.23k]
  ------------------
   35|    196|  {
   36|    196|    return 1.0;
   37|    196|  }
   38|  8.23k|  if(str == "false")
  ------------------
  |  Branch (38:6): [True: 194, False: 8.03k]
  ------------------
   39|    194|  {
   40|    194|    return 0.0;
   41|    194|  }
   42|  8.03k|  if(env.enums)
  ------------------
  |  Branch (42:6): [True: 8.03k, False: 0]
  ------------------
   43|  8.03k|  {
   44|  8.03k|    auto it = env.enums->find(str);
   45|  8.03k|    if(it != env.enums->end())
  ------------------
  |  Branch (45:8): [True: 0, False: 8.03k]
  ------------------
   46|      0|    {
   47|      0|      return it->second;
   48|      0|    }
   49|  8.03k|  }
   50|  8.03k|  return value.cast<double>();
   51|  8.03k|}
_ZZNK2BT3Ast14ExprAssignment8evaluateERNS0_11EnvironmentEENKUlvE_clB5cxx11Ev:
  548|     55|    auto errorPrefix = [dst_ptr, &key]() {
  549|     55|      return StrCat("Error assigning a value to entry [", key, "] with type [",
  550|     55|                    BT::demangle(dst_ptr->type()), "]. ");
  551|     55|    };
_ZN2BT3Ast6ExprIfC2ESt10shared_ptrINS0_8ExprBaseEES4_S4_:
  453|  1.76k|    : condition(std::move(condition)), then(std::move(then)), else_(std::move(else_))
  454|  1.76k|  {}
_ZNK2BT3Ast6ExprIf8evaluateERNS0_11EnvironmentE:
  457|    680|  {
  458|    680|    const auto& v = condition->evaluate(env);
  459|    680|    bool valid = (v.isType<SimpleString>() && v.cast<SimpleString>().size() > 0) ||
  ------------------
  |  Branch (459:19): [True: 0, False: 680]
  |  Branch (459:47): [True: 0, False: 0]
  ------------------
  460|    673|                 (v.cast<double>() != 0.0);
  ------------------
  |  Branch (460:18): [True: 264, False: 409]
  ------------------
  461|    680|    if(valid)
  ------------------
  |  Branch (461:8): [True: 260, False: 420]
  ------------------
  462|    260|    {
  463|    260|      return then->evaluate(env);
  464|    260|    }
  465|    420|    else
  466|    420|    {
  467|    420|      return else_->evaluate(env);
  468|    420|    }
  469|    680|  }
_ZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentE:
  352|  13.9k|  {
  353|  13.9k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  354|  13.9k|      switch(op)
  355|  13.9k|      {
  356|  13.9k|        case equal:
  357|  13.9k|          if(!IsSame(lv, rv))
  358|  13.9k|            return false;
  359|  13.9k|          break;
  360|  13.9k|        case not_equal:
  361|  13.9k|          if(IsSame(lv, rv))
  362|  13.9k|            return false;
  363|  13.9k|          break;
  364|  13.9k|        case less:
  365|  13.9k|          if(lv >= rv)
  366|  13.9k|            return false;
  367|  13.9k|          break;
  368|  13.9k|        case greater:
  369|  13.9k|          if(lv <= rv)
  370|  13.9k|            return false;
  371|  13.9k|          break;
  372|  13.9k|        case less_equal:
  373|  13.9k|          if(lv > rv)
  374|  13.9k|            return false;
  375|  13.9k|          break;
  376|  13.9k|        case greater_equal:
  377|  13.9k|          if(lv < rv)
  378|  13.9k|            return false;
  379|  13.9k|          break;
  380|  13.9k|      }
  381|  13.9k|      return true;
  382|  13.9k|    };
  383|       |
  384|  13.9k|    auto lhs_v = operands[0]->evaluate(env);
  385|   142k|    for(auto i = 0u; i != ops.size(); ++i)
  ------------------
  |  Branch (385:22): [True: 137k, False: 4.84k]
  ------------------
  386|   137k|    {
  387|   137k|      auto rhs_v = operands[i + 1]->evaluate(env);
  388|       |
  389|   137k|      if(lhs_v.empty())
  ------------------
  |  Branch (389:10): [True: 9, False: 137k]
  ------------------
  390|      9|      {
  391|      9|        throw RuntimeError(ErrorNotInit("left", opStr(ops[i])));
  392|      9|      }
  393|   137k|      if(rhs_v.empty())
  ------------------
  |  Branch (393:10): [True: 3, False: 137k]
  ------------------
  394|      3|      {
  395|      3|        throw RuntimeError(ErrorNotInit("right", opStr(ops[i])));
  396|      3|      }
  397|   137k|      const Any False(0.0);
  398|       |
  399|   137k|      if(lhs_v.isNumber() && rhs_v.isNumber())
  ------------------
  |  Branch (399:10): [True: 124k, False: 13.0k]
  |  Branch (399:30): [True: 120k, False: 3.77k]
  ------------------
  400|   120k|      {
  401|   120k|        auto lv = lhs_v.cast<double>();
  402|   120k|        auto rv = rhs_v.cast<double>();
  403|   120k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (403:12): [True: 1.24k, False: 119k]
  ------------------
  404|  1.24k|        {
  405|  1.24k|          return False;
  406|  1.24k|        }
  407|   120k|      }
  408|  16.8k|      else if(lhs_v.isString() && rhs_v.isString())
  ------------------
  |  Branch (408:15): [True: 12.5k, False: 4.30k]
  |  Branch (408:35): [True: 8.72k, False: 3.82k]
  ------------------
  409|  8.72k|      {
  410|  8.72k|        auto lv = lhs_v.cast<SimpleString>();
  411|  8.72k|        auto rv = rhs_v.cast<SimpleString>();
  412|  8.72k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (412:12): [True: 4.27k, False: 4.44k]
  ------------------
  413|  4.27k|        {
  414|  4.27k|          return False;
  415|  4.27k|        }
  416|  8.72k|      }
  417|  8.12k|      else if(lhs_v.isString() && rhs_v.isNumber())
  ------------------
  |  Branch (417:15): [True: 3.82k, False: 4.30k]
  |  Branch (417:35): [True: 3.82k, False: 0]
  ------------------
  418|  3.82k|      {
  419|  3.82k|        auto lv = StringToDouble(lhs_v, env);
  420|  3.82k|        auto rv = rhs_v.cast<double>();
  421|  3.82k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (421:12): [True: 1.42k, False: 2.39k]
  ------------------
  422|  1.42k|        {
  423|  1.42k|          return False;
  424|  1.42k|        }
  425|  3.82k|      }
  426|  4.30k|      else if(lhs_v.isNumber() && rhs_v.isString())
  ------------------
  |  Branch (426:15): [True: 3.77k, False: 528]
  |  Branch (426:35): [True: 3.77k, False: 0]
  ------------------
  427|  3.77k|      {
  428|  3.77k|        auto lv = lhs_v.cast<double>();
  429|  3.77k|        auto rv = StringToDouble(rhs_v, env);
  430|  3.77k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (430:12): [True: 1.58k, False: 2.19k]
  ------------------
  431|  1.58k|        {
  432|  1.58k|          return False;
  433|  1.58k|        }
  434|  3.77k|      }
  435|    528|      else
  436|    528|      {
  437|    528|        throw RuntimeError(StrCat("Can't mix different types in Comparison. "
  438|    528|                                  "Left operand [",
  439|    528|                                  BT::demangle(lhs_v.type()), "] right operand [",
  440|    528|                                  BT::demangle(rhs_v.type()), "]"));
  441|    528|      }
  442|   128k|      lhs_v = rhs_v;
  443|   128k|    }
  444|  4.84k|    return Any(1.0);
  445|  13.9k|  }
_ZNK2BT3Ast14ExprComparison5opStrENS1_4op_tE:
  329|     12|  {
  330|     12|    switch(op)
  ------------------
  |  Branch (330:12): [True: 12, False: 0]
  ------------------
  331|     12|    {
  332|      1|      case equal:
  ------------------
  |  Branch (332:7): [True: 1, False: 11]
  ------------------
  333|      1|        return "==";
  334|      1|      case not_equal:
  ------------------
  |  Branch (334:7): [True: 1, False: 11]
  ------------------
  335|      1|        return "!=";
  336|      3|      case less:
  ------------------
  |  Branch (336:7): [True: 3, False: 9]
  ------------------
  337|      3|        return "<";
  338|      6|      case greater:
  ------------------
  |  Branch (338:7): [True: 6, False: 6]
  ------------------
  339|      6|        return ">";
  340|      0|      case less_equal:
  ------------------
  |  Branch (340:7): [True: 0, False: 12]
  ------------------
  341|      0|        return "<=";
  342|      1|      case greater_equal:
  ------------------
  |  Branch (342:7): [True: 1, False: 11]
  ------------------
  343|      1|        return ">=";
  344|     12|    }
  345|      0|    return "";
  346|     12|  }
_ZZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentEENKUlRKT_RKT0_NS1_4op_tEE_clIddEEDaS6_S9_SA_:
  353|   127k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  354|   127k|      switch(op)
  ------------------
  |  Branch (354:14): [True: 127k, False: 0]
  ------------------
  355|   127k|      {
  356|  2.44k|        case equal:
  ------------------
  |  Branch (356:9): [True: 2.44k, False: 125k]
  ------------------
  357|  2.44k|          if(!IsSame(lv, rv))
  ------------------
  |  Branch (357:14): [True: 754, False: 1.69k]
  ------------------
  358|    754|            return false;
  359|  1.69k|          break;
  360|  57.7k|        case not_equal:
  ------------------
  |  Branch (360:9): [True: 57.7k, False: 70.0k]
  ------------------
  361|  57.7k|          if(IsSame(lv, rv))
  ------------------
  |  Branch (361:14): [True: 587, False: 57.1k]
  ------------------
  362|    587|            return false;
  363|  57.1k|          break;
  364|  57.1k|        case less:
  ------------------
  |  Branch (364:9): [True: 4.55k, False: 123k]
  ------------------
  365|  4.55k|          if(lv >= rv)
  ------------------
  |  Branch (365:14): [True: 872, False: 3.68k]
  ------------------
  366|    872|            return false;
  367|  3.68k|          break;
  368|  60.3k|        case greater:
  ------------------
  |  Branch (368:9): [True: 60.3k, False: 67.4k]
  ------------------
  369|  60.3k|          if(lv <= rv)
  ------------------
  |  Branch (369:14): [True: 739, False: 59.6k]
  ------------------
  370|    739|            return false;
  371|  59.6k|          break;
  372|  59.6k|        case less_equal:
  ------------------
  |  Branch (372:9): [True: 1.33k, False: 126k]
  ------------------
  373|  1.33k|          if(lv > rv)
  ------------------
  |  Branch (373:14): [True: 704, False: 635]
  ------------------
  374|    704|            return false;
  375|    635|          break;
  376|  1.37k|        case greater_equal:
  ------------------
  |  Branch (376:9): [True: 1.37k, False: 126k]
  ------------------
  377|  1.37k|          if(lv < rv)
  ------------------
  |  Branch (377:14): [True: 600, False: 778]
  ------------------
  378|    600|            return false;
  379|    778|          break;
  380|   127k|      }
  381|   123k|      return true;
  382|   127k|    };
_ZN2BT3Ast6IsSameIdEEbRKT_S4_:
  304|  60.1k|{
  305|       |  if constexpr(std::is_same_v<double, T>)
  306|  60.1k|  {
  307|  60.1k|    constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
  308|  60.1k|    return std::abs(lv - rv) <= EPS;
  309|       |  }
  310|       |  else
  311|       |  {
  312|       |    return (lv == rv);
  313|       |  }
  314|  60.1k|}
_ZZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentEENKUlRKT_RKT0_NS1_4op_tEE_clIN7SafeAny12SimpleStringESE_EEDaS6_S9_SA_:
  353|  8.72k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  354|  8.72k|      switch(op)
  ------------------
  |  Branch (354:14): [True: 8.72k, False: 0]
  ------------------
  355|  8.72k|      {
  356|  1.11k|        case equal:
  ------------------
  |  Branch (356:9): [True: 1.11k, False: 7.60k]
  ------------------
  357|  1.11k|          if(!IsSame(lv, rv))
  ------------------
  |  Branch (357:14): [True: 585, False: 530]
  ------------------
  358|    585|            return false;
  359|    530|          break;
  360|  1.00k|        case not_equal:
  ------------------
  |  Branch (360:9): [True: 1.00k, False: 7.72k]
  ------------------
  361|  1.00k|          if(IsSame(lv, rv))
  ------------------
  |  Branch (361:14): [True: 405, False: 598]
  ------------------
  362|    405|            return false;
  363|    598|          break;
  364|  1.82k|        case less:
  ------------------
  |  Branch (364:9): [True: 1.82k, False: 6.89k]
  ------------------
  365|  1.82k|          if(lv >= rv)
  ------------------
  |  Branch (365:14): [True: 1.23k, False: 589]
  ------------------
  366|  1.23k|            return false;
  367|    589|          break;
  368|  1.61k|        case greater:
  ------------------
  |  Branch (368:9): [True: 1.61k, False: 7.11k]
  ------------------
  369|  1.61k|          if(lv <= rv)
  ------------------
  |  Branch (369:14): [True: 752, False: 860]
  ------------------
  370|    752|            return false;
  371|    860|          break;
  372|  1.36k|        case less_equal:
  ------------------
  |  Branch (372:9): [True: 1.36k, False: 7.36k]
  ------------------
  373|  1.36k|          if(lv > rv)
  ------------------
  |  Branch (373:14): [True: 537, False: 823]
  ------------------
  374|    537|            return false;
  375|    823|          break;
  376|  1.80k|        case greater_equal:
  ------------------
  |  Branch (376:9): [True: 1.80k, False: 6.91k]
  ------------------
  377|  1.80k|          if(lv < rv)
  ------------------
  |  Branch (377:14): [True: 762, False: 1.04k]
  ------------------
  378|    762|            return false;
  379|  1.04k|          break;
  380|  8.72k|      }
  381|  4.44k|      return true;
  382|  8.72k|    };
_ZN2BT3Ast6IsSameIN7SafeAny12SimpleStringEEEbRKT_S6_:
  304|  2.11k|{
  305|       |  if constexpr(std::is_same_v<double, T>)
  306|       |  {
  307|       |    constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
  308|       |    return std::abs(lv - rv) <= EPS;
  309|       |  }
  310|       |  else
  311|  2.11k|  {
  312|  2.11k|    return (lv == rv);
  313|  2.11k|  }
  314|  2.11k|}
_ZN2BT3Ast20ExprBinaryArithmeticC2ESt10shared_ptrINS0_8ExprBaseEENS1_4op_tES4_:
  199|  86.6k|    : op(op), lhs(std::move(lhs)), rhs(std::move(rhs))
  200|  86.6k|  {}
_ZNK2BT3Ast20ExprBinaryArithmetic8evaluateERNS0_11EnvironmentE:
  203|  14.3k|  {
  204|  14.3k|    auto lhs_v = lhs->evaluate(env);
  205|  14.3k|    auto rhs_v = rhs->evaluate(env);
  206|       |
  207|  14.3k|    if(lhs_v.empty())
  ------------------
  |  Branch (207:8): [True: 12, False: 14.2k]
  ------------------
  208|     12|    {
  209|     12|      throw RuntimeError(ErrorNotInit("left", opStr()));
  210|     12|    }
  211|  14.2k|    if(rhs_v.empty())
  ------------------
  |  Branch (211:8): [True: 3, False: 14.2k]
  ------------------
  212|      3|    {
  213|      3|      throw RuntimeError(ErrorNotInit("right", opStr()));
  214|      3|    }
  215|       |
  216|  14.2k|    if(rhs_v.isNumber() && lhs_v.isNumber())
  ------------------
  |  Branch (216:8): [True: 6.17k, False: 8.12k]
  |  Branch (216:28): [True: 4.41k, False: 1.75k]
  ------------------
  217|  4.41k|    {
  218|  4.41k|      auto lv = lhs_v.cast<double>();
  219|  4.41k|      auto rv = rhs_v.cast<double>();
  220|       |
  221|  4.41k|      switch(op)
  222|  4.41k|      {
  223|    448|        case plus:
  ------------------
  |  Branch (223:9): [True: 448, False: 3.97k]
  ------------------
  224|    448|          return Any(lv + rv);
  225|    578|        case minus:
  ------------------
  |  Branch (225:9): [True: 578, False: 3.84k]
  ------------------
  226|    578|          return Any(lv - rv);
  227|    302|        case times:
  ------------------
  |  Branch (227:9): [True: 302, False: 4.11k]
  ------------------
  228|    302|          return Any(lv * rv);
  229|    270|        case div:
  ------------------
  |  Branch (229:9): [True: 270, False: 4.14k]
  ------------------
  230|    270|          return Any(lv / rv);
  231|  2.81k|        default: {
  ------------------
  |  Branch (231:9): [True: 2.81k, False: 1.60k]
  ------------------
  232|  2.81k|        }
  233|  4.41k|      }
  234|       |
  235|  2.81k|      if(op == bit_and || op == bit_or || op == bit_xor)
  ------------------
  |  Branch (235:10): [True: 724, False: 2.09k]
  |  Branch (235:27): [True: 267, False: 1.82k]
  |  Branch (235:43): [True: 272, False: 1.55k]
  ------------------
  236|  1.26k|      {
  237|  1.26k|        try
  238|  1.26k|        {
  239|  1.26k|          int64_t li = lhs_v.cast<int64_t>();
  240|  1.26k|          int64_t ri = rhs_v.cast<int64_t>();
  241|  1.26k|          switch(op)
  242|  1.26k|          {
  243|    723|            case bit_and:
  ------------------
  |  Branch (243:13): [True: 723, False: 540]
  ------------------
  244|    723|              return Any(static_cast<double>(li & ri));
  245|    263|            case bit_or:
  ------------------
  |  Branch (245:13): [True: 263, False: 1.00k]
  ------------------
  246|    263|              return Any(static_cast<double>(li | ri));
  247|    270|            case bit_xor:
  ------------------
  |  Branch (247:13): [True: 270, False: 993]
  ------------------
  248|    270|              return Any(static_cast<double>(li ^ ri));
  249|      0|            default: {
  ------------------
  |  Branch (249:13): [True: 0, False: 1.26k]
  ------------------
  250|      0|            }
  251|  1.26k|          }
  252|  1.26k|        }
  253|  1.26k|        catch(...)
  254|  1.26k|        {
  255|      7|          throw RuntimeError("Binary operators are not allowed if "
  256|      7|                             "one of the operands is not an integer");
  257|      7|        }
  258|  1.26k|      }
  259|       |
  260|  1.55k|      if(op == logic_or || op == logic_and)
  ------------------
  |  Branch (260:10): [True: 614, False: 942]
  |  Branch (260:28): [True: 718, False: 224]
  ------------------
  261|  1.33k|      {
  262|  1.33k|        try
  263|  1.33k|        {
  264|  1.33k|          auto lb = lhs_v.cast<bool>();
  265|  1.33k|          auto rb = rhs_v.cast<bool>();
  266|  1.33k|          switch(op)
  267|  1.33k|          {
  268|    588|            case logic_or:
  ------------------
  |  Branch (268:13): [True: 588, False: 744]
  ------------------
  269|    588|              return Any(static_cast<double>(lb || rb));
  ------------------
  |  Branch (269:46): [True: 220, False: 368]
  |  Branch (269:52): [True: 4, False: 364]
  ------------------
  270|    607|            case logic_and:
  ------------------
  |  Branch (270:13): [True: 607, False: 725]
  ------------------
  271|    607|              return Any(static_cast<double>(lb && rb));
  ------------------
  |  Branch (271:46): [True: 321, False: 286]
  |  Branch (271:52): [True: 314, False: 7]
  ------------------
  272|      0|            default: {
  ------------------
  |  Branch (272:13): [True: 0, False: 1.33k]
  ------------------
  273|      0|            }
  274|  1.33k|          }
  275|  1.33k|        }
  276|  1.33k|        catch(...)
  277|  1.33k|        {
  278|    137|          throw RuntimeError("Logic operators are not allowed if "
  279|    137|                             "one of the operands is not castable to bool");
  280|    137|        }
  281|  1.33k|      }
  282|  1.55k|    }
  283|  9.87k|    else if(rhs_v.isString() && lhs_v.isString() && op == plus)
  ------------------
  |  Branch (283:13): [True: 7.83k, False: 2.04k]
  |  Branch (283:33): [True: 6.17k, False: 1.66k]
  |  Branch (283:53): [True: 5.76k, False: 406]
  ------------------
  284|  5.76k|    {
  285|  5.76k|      return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
  286|  5.76k|    }
  287|  4.11k|    else if(op == concat && ((rhs_v.isString() && lhs_v.isString()) ||
  ------------------
  |  Branch (287:13): [True: 3.79k, False: 313]
  |  Branch (287:31): [True: 2.05k, False: 1.74k]
  |  Branch (287:51): [True: 399, False: 1.65k]
  ------------------
  288|  3.40k|                             (rhs_v.isString() && lhs_v.isNumber()) ||
  ------------------
  |  Branch (288:31): [True: 1.65k, False: 1.74k]
  |  Branch (288:51): [True: 1.65k, False: 0]
  ------------------
  289|  1.74k|                             (rhs_v.isNumber() && lhs_v.isString())))
  ------------------
  |  Branch (289:31): [True: 1.74k, False: 0]
  |  Branch (289:51): [True: 1.74k, False: 0]
  ------------------
  290|  3.79k|    {
  291|  3.79k|      return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
  292|  3.79k|    }
  293|    313|    else
  294|    313|    {
  295|    313|      throw RuntimeError("Operation not permitted");
  296|    313|    }
  297|       |
  298|    224|    return {};  // unreachable
  299|  14.2k|  }
_ZNK2BT3Ast20ExprBinaryArithmetic5opStrEv:
  169|     15|  {
  170|     15|    switch(op)
  ------------------
  |  Branch (170:12): [True: 15, False: 0]
  ------------------
  171|     15|    {
  172|      1|      case plus:
  ------------------
  |  Branch (172:7): [True: 1, False: 14]
  ------------------
  173|      1|        return "+";
  174|      3|      case minus:
  ------------------
  |  Branch (174:7): [True: 3, False: 12]
  ------------------
  175|      3|        return "-";
  176|      1|      case times:
  ------------------
  |  Branch (176:7): [True: 1, False: 14]
  ------------------
  177|      1|        return "*";
  178|      4|      case div:
  ------------------
  |  Branch (178:7): [True: 4, False: 11]
  ------------------
  179|      4|        return "/";
  180|      0|      case concat:
  ------------------
  |  Branch (180:7): [True: 0, False: 15]
  ------------------
  181|      0|        return "..";
  182|      3|      case bit_and:
  ------------------
  |  Branch (182:7): [True: 3, False: 12]
  ------------------
  183|      3|        return "&";
  184|      1|      case bit_or:
  ------------------
  |  Branch (184:7): [True: 1, False: 14]
  ------------------
  185|      1|        return "|";
  186|      1|      case bit_xor:
  ------------------
  |  Branch (186:7): [True: 1, False: 14]
  ------------------
  187|      1|        return "^";
  188|      0|      case logic_and:
  ------------------
  |  Branch (188:7): [True: 0, False: 15]
  ------------------
  189|      0|        return "&&";
  190|      1|      case logic_or:
  ------------------
  |  Branch (190:7): [True: 1, False: 14]
  ------------------
  191|      1|        return "||";
  192|     15|    }
  193|      0|    return "";
  194|     15|  }

_ZN7SafeAny7details13convertNumberIldEEvRKT_RT0_:
  145|   254k|{
  146|   254k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  147|   254k|                                                                          "convertible");
  148|       |
  149|   254k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (149:34): [True: 0, Folded]
  |  Branch (149:55): [Folded, False: 0]
  ------------------
  150|       |
  151|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  152|       |  {
  153|       |    if(source < 0)
  154|       |    {
  155|       |      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  156|       |    }
  157|       |  }
  158|       |  // these conversions are always safe (no check needed):
  159|       |  // - same type
  160|       |  // - float -> double
  161|       |  // - floating point to bool (C-style: any non-zero is true)
  162|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  163|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  164|       |  {
  165|       |    target = static_cast<DST>(source);
  166|       |  }
  167|       |  // integer to bool: only 0 and 1 are valid
  168|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  169|       |  {
  170|       |    checkLowerLimit<SRC, DST>(source);
  171|       |    target = static_cast<DST>(source);
  172|       |  }
  173|       |  else if constexpr(both_integers)
  174|       |  {
  175|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  176|       |    {
  177|       |      checkUpperLimit<SRC, DST>(source);
  178|       |    }
  179|       |    // casting to a smaller number need to be check
  180|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  181|       |    {
  182|       |      if constexpr(is_signed<SRC>())
  183|       |      {
  184|       |        checkLowerLimit<SRC, DST>(source);
  185|       |      }
  186|       |      checkUpperLimit<SRC, DST>(source);
  187|       |    }
  188|       |    target = static_cast<DST>(source);
  189|       |  }
  190|       |  // casting to/from floating points might cause truncation.
  191|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  192|       |                    std::is_floating_point<DST>::value)
  193|   254k|  {
  194|   254k|    bool both_float =
  195|   254k|        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  ------------------
  |  Branch (195:9): [Folded, False: 254k]
  |  Branch (195:47): [True: 0, Folded]
  ------------------
  196|       |    // to avoid being too pedantic, let's accept casting between double and float
  197|   254k|    if(!both_float)
  ------------------
  |  Branch (197:8): [True: 254k, False: 0]
  ------------------
  198|   254k|    {
  199|   254k|      checkTruncation<SRC, DST>(source);
  200|   254k|    }
  201|   254k|    target = static_cast<DST>(source);
  202|   254k|  }
  203|   254k|}
_ZN7SafeAny7details15checkTruncationIldEEvRKT_:
   92|   254k|{
   93|       |  // Handle integer to floating point
   94|       |  if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>)
   95|   254k|  {
   96|       |    // Check if value can be represented exactly in the target type
   97|   254k|    constexpr uint64_t max_exact = (1LL << std::numeric_limits<double>::digits) - 1;
   98|   254k|    bool doesnt_fit = false;
   99|       |    if constexpr(!std::is_signed_v<From>)
  100|       |    {
  101|       |      doesnt_fit = static_cast<uint64_t>(from) > max_exact;
  102|       |    }
  103|       |    else
  104|   254k|    {
  105|   254k|      doesnt_fit = std::abs(static_cast<int64_t>(from)) > static_cast<int64_t>(max_exact);
  106|   254k|    }
  107|   254k|    if(doesnt_fit)
  ------------------
  |  Branch (107:8): [True: 21, False: 254k]
  ------------------
  108|     21|    {
  109|     21|      throw std::runtime_error("Loss of precision when converting a large integer number "
  110|     21|                               "to floating point:" +
  111|     21|                               std::to_string(from));
  112|     21|    }
  113|       |  }
  114|       |  // Handle floating point to integer
  115|       |  else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>)
  116|       |  {
  117|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  118|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()) ||
  119|       |       from != std::nearbyint(from))
  120|       |    {
  121|       |      throw std::runtime_error("Invalid floating point to integer conversion");
  122|       |    }
  123|       |  }
  124|       |  // Handle other conversions
  125|       |  else
  126|       |  {
  127|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  128|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()))
  129|       |    {
  130|       |      throw std::runtime_error("Value outside numeric limits");
  131|       |    }
  132|       |    To as_target = static_cast<To>(from);
  133|       |    From back_to_source = static_cast<From>(as_target);
  134|       |    if(from != back_to_source)
  135|       |    {
  136|       |      throw std::runtime_error("Value truncated in conversion");
  137|       |    }
  138|       |  }
  139|   254k|}
_ZN7SafeAny7details13convertNumberIdlEEvRKT_RT0_:
  145|  2.31k|{
  146|  2.31k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  147|  2.31k|                                                                          "convertible");
  148|       |
  149|  2.31k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (149:34): [Folded, False: 2.31k]
  |  Branch (149:55): [True: 0, Folded]
  ------------------
  150|       |
  151|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  152|       |  {
  153|       |    if(source < 0)
  154|       |    {
  155|       |      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  156|       |    }
  157|       |  }
  158|       |  // these conversions are always safe (no check needed):
  159|       |  // - same type
  160|       |  // - float -> double
  161|       |  // - floating point to bool (C-style: any non-zero is true)
  162|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  163|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  164|       |  {
  165|       |    target = static_cast<DST>(source);
  166|       |  }
  167|       |  // integer to bool: only 0 and 1 are valid
  168|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  169|       |  {
  170|       |    checkLowerLimit<SRC, DST>(source);
  171|       |    target = static_cast<DST>(source);
  172|       |  }
  173|       |  else if constexpr(both_integers)
  174|       |  {
  175|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  176|       |    {
  177|       |      checkUpperLimit<SRC, DST>(source);
  178|       |    }
  179|       |    // casting to a smaller number need to be check
  180|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  181|       |    {
  182|       |      if constexpr(is_signed<SRC>())
  183|       |      {
  184|       |        checkLowerLimit<SRC, DST>(source);
  185|       |      }
  186|       |      checkUpperLimit<SRC, DST>(source);
  187|       |    }
  188|       |    target = static_cast<DST>(source);
  189|       |  }
  190|       |  // casting to/from floating points might cause truncation.
  191|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  192|       |                    std::is_floating_point<DST>::value)
  193|  2.31k|  {
  194|  2.31k|    bool both_float =
  195|  2.31k|        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  ------------------
  |  Branch (195:9): [True: 2.31k, Folded]
  |  Branch (195:47): [Folded, False: 2.31k]
  ------------------
  196|       |    // to avoid being too pedantic, let's accept casting between double and float
  197|  2.31k|    if(!both_float)
  ------------------
  |  Branch (197:8): [True: 2.31k, False: 0]
  ------------------
  198|  2.31k|    {
  199|  2.31k|      checkTruncation<SRC, DST>(source);
  200|  2.31k|    }
  201|  2.31k|    target = static_cast<DST>(source);
  202|  2.31k|  }
  203|  2.31k|}
_ZN7SafeAny7details15checkTruncationIdlEEvRKT_:
   92|  2.31k|{
   93|       |  // Handle integer to floating point
   94|       |  if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>)
   95|       |  {
   96|       |    // Check if value can be represented exactly in the target type
   97|       |    constexpr uint64_t max_exact = (1LL << std::numeric_limits<double>::digits) - 1;
   98|       |    bool doesnt_fit = false;
   99|       |    if constexpr(!std::is_signed_v<From>)
  100|       |    {
  101|       |      doesnt_fit = static_cast<uint64_t>(from) > max_exact;
  102|       |    }
  103|       |    else
  104|       |    {
  105|       |      doesnt_fit = std::abs(static_cast<int64_t>(from)) > static_cast<int64_t>(max_exact);
  106|       |    }
  107|       |    if(doesnt_fit)
  108|       |    {
  109|       |      throw std::runtime_error("Loss of precision when converting a large integer number "
  110|       |                               "to floating point:" +
  111|       |                               std::to_string(from));
  112|       |    }
  113|       |  }
  114|       |  // Handle floating point to integer
  115|       |  else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>)
  116|  2.31k|  {
  117|  2.31k|    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  ------------------
  |  Branch (117:8): [True: 2, False: 2.31k]
  ------------------
  118|  2.31k|       from < static_cast<From>(std::numeric_limits<To>::lowest()) ||
  ------------------
  |  Branch (118:8): [True: 2, False: 2.30k]
  ------------------
  119|  2.30k|       from != std::nearbyint(from))
  ------------------
  |  Branch (119:8): [True: 7, False: 2.30k]
  ------------------
  120|     11|    {
  121|     11|      throw std::runtime_error("Invalid floating point to integer conversion");
  122|     11|    }
  123|       |  }
  124|       |  // Handle other conversions
  125|       |  else
  126|       |  {
  127|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  128|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()))
  129|       |    {
  130|       |      throw std::runtime_error("Value outside numeric limits");
  131|       |    }
  132|       |    To as_target = static_cast<To>(from);
  133|       |    From back_to_source = static_cast<From>(as_target);
  134|       |    if(from != back_to_source)
  135|       |    {
  136|       |      throw std::runtime_error("Value truncated in conversion");
  137|       |    }
  138|       |  }
  139|  2.31k|}
_ZN7SafeAny7details13convertNumberIlbEEvRKT_RT0_:
  145|  1.49k|{
  146|  1.49k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  147|  1.49k|                                                                          "convertible");
  148|       |
  149|  1.49k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (149:34): [True: 0, Folded]
  |  Branch (149:55): [True: 0, Folded]
  ------------------
  150|       |
  151|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  152|  1.49k|  {
  153|  1.49k|    if(source < 0)
  ------------------
  |  Branch (153:8): [True: 55, False: 1.44k]
  ------------------
  154|     55|    {
  155|     55|      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  156|     55|    }
  157|  1.49k|  }
  158|       |  // these conversions are always safe (no check needed):
  159|       |  // - same type
  160|       |  // - float -> double
  161|       |  // - floating point to bool (C-style: any non-zero is true)
  162|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  163|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  164|       |  {
  165|       |    target = static_cast<DST>(source);
  166|       |  }
  167|       |  // integer to bool: only 0 and 1 are valid
  168|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  169|  1.49k|  {
  170|  1.49k|    checkLowerLimit<SRC, DST>(source);
  171|  1.49k|    target = static_cast<DST>(source);
  172|       |  }
  173|       |  else if constexpr(both_integers)
  174|       |  {
  175|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  176|       |    {
  177|       |      checkUpperLimit<SRC, DST>(source);
  178|       |    }
  179|       |    // casting to a smaller number need to be check
  180|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  181|       |    {
  182|       |      if constexpr(is_signed<SRC>())
  183|       |      {
  184|       |        checkLowerLimit<SRC, DST>(source);
  185|       |      }
  186|       |      checkUpperLimit<SRC, DST>(source);
  187|       |    }
  188|       |    target = static_cast<DST>(source);
  189|       |  }
  190|       |  // casting to/from floating points might cause truncation.
  191|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  192|       |                    std::is_floating_point<DST>::value)
  193|       |  {
  194|       |    bool both_float =
  195|       |        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  196|       |    // to avoid being too pedantic, let's accept casting between double and float
  197|       |    if(!both_float)
  198|       |    {
  199|       |      checkTruncation<SRC, DST>(source);
  200|       |    }
  201|       |    target = static_cast<DST>(source);
  202|       |  }
  203|  1.49k|}
_ZN7SafeAny7details15checkLowerLimitIlbEEvRKT_:
   76|  1.44k|{
   77|       |  if constexpr(std::is_same<To, bool>::value)
   78|  1.44k|  {
   79|  1.44k|    if(from != 0 && from != 1)
  ------------------
  |  Branch (79:8): [True: 720, False: 723]
  |  Branch (79:21): [True: 80, False: 640]
  ------------------
   80|     80|    {
   81|     80|      throw std::runtime_error("Implicit casting to bool is not allowed");
   82|     80|    }
   83|       |  }
   84|       |  else if(from < std::numeric_limits<To>::min())
   85|       |  {
   86|       |    throw std::runtime_error("Value outside the lovest numerical limit.");
   87|       |  }
   88|  1.44k|}
_ZN7SafeAny7details13convertNumberIdbEEvRKT_RT0_:
  145|  1.06k|{
  146|  1.06k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  147|  1.06k|                                                                          "convertible");
  148|       |
  149|  1.06k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (149:34): [Folded, False: 1.06k]
  |  Branch (149:55): [True: 0, Folded]
  ------------------
  150|       |
  151|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  152|  1.06k|  {
  153|  1.06k|    if(source < 0)
  ------------------
  |  Branch (153:8): [True: 2, False: 1.06k]
  ------------------
  154|      2|    {
  155|      2|      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  156|      2|    }
  157|  1.06k|  }
  158|       |  // these conversions are always safe (no check needed):
  159|       |  // - same type
  160|       |  // - float -> double
  161|       |  // - floating point to bool (C-style: any non-zero is true)
  162|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  163|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  164|  1.06k|  {
  165|  1.06k|    target = static_cast<DST>(source);
  166|       |  }
  167|       |  // integer to bool: only 0 and 1 are valid
  168|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  169|       |  {
  170|       |    checkLowerLimit<SRC, DST>(source);
  171|       |    target = static_cast<DST>(source);
  172|       |  }
  173|       |  else if constexpr(both_integers)
  174|       |  {
  175|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  176|       |    {
  177|       |      checkUpperLimit<SRC, DST>(source);
  178|       |    }
  179|       |    // casting to a smaller number need to be check
  180|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  181|       |    {
  182|       |      if constexpr(is_signed<SRC>())
  183|       |      {
  184|       |        checkLowerLimit<SRC, DST>(source);
  185|       |      }
  186|       |      checkUpperLimit<SRC, DST>(source);
  187|       |    }
  188|       |    target = static_cast<DST>(source);
  189|       |  }
  190|       |  // casting to/from floating points might cause truncation.
  191|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  192|       |                    std::is_floating_point<DST>::value)
  193|       |  {
  194|       |    bool both_float =
  195|       |        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  196|       |    // to avoid being too pedantic, let's accept casting between double and float
  197|       |    if(!both_float)
  198|       |    {
  199|       |      checkTruncation<SRC, DST>(source);
  200|       |    }
  201|       |    target = static_cast<DST>(source);
  202|       |  }
  203|  1.06k|}

_ZN2BT8demangleB5cxx11ERKSt10type_index:
   86|  16.4k|{
   87|  16.4k|  if(index == typeid(std::string))
  ------------------
  |  Branch (87:6): [True: 100, False: 16.3k]
  ------------------
   88|    100|  {
   89|    100|    return "std::string";
   90|    100|  }
   91|  16.3k|  if(index == typeid(std::string_view))
  ------------------
  |  Branch (91:6): [True: 0, False: 16.3k]
  ------------------
   92|      0|  {
   93|      0|    return "std::string_view";
   94|      0|  }
   95|  16.3k|  if(index == typeid(std::chrono::seconds))
  ------------------
  |  Branch (95:6): [True: 0, False: 16.3k]
  ------------------
   96|      0|  {
   97|      0|    return "std::chrono::seconds";
   98|      0|  }
   99|  16.3k|  if(index == typeid(std::chrono::milliseconds))
  ------------------
  |  Branch (99:6): [True: 0, False: 16.3k]
  ------------------
  100|      0|  {
  101|      0|    return "std::chrono::milliseconds";
  102|      0|  }
  103|  16.3k|  if(index == typeid(std::chrono::microseconds))
  ------------------
  |  Branch (103:6): [True: 0, False: 16.3k]
  ------------------
  104|      0|  {
  105|      0|    return "std::chrono::microseconds";
  106|      0|  }
  107|       |
  108|  16.3k|  scoped_demangled_name demangled_name(index.name());
  109|  16.3k|  char const* const p = demangled_name.get();
  110|  16.3k|  if(p != nullptr)
  ------------------
  |  Branch (110:6): [True: 16.3k, False: 0]
  ------------------
  111|  16.3k|  {
  112|  16.3k|    return p;
  113|  16.3k|  }
  114|      0|  return index.name();
  115|  16.3k|}
_ZN2BT21scoped_demangled_nameC2EPKc:
   34|  16.3k|  explicit scoped_demangled_name(char const* name) noexcept : m_p(demangle_alloc(name))
   35|  16.3k|  {}
_ZN2BT14demangle_allocEPKc:
   56|  16.3k|{
   57|  16.3k|  int status = 0;
   58|  16.3k|  std::size_t size = 0;
   59|       |  return abi::__cxa_demangle(name, NULL, &size, &status);
   60|  16.3k|}
_ZNK2BT21scoped_demangled_name3getEv:
   43|  16.3k|  {
   44|  16.3k|    return m_p;
   45|  16.3k|  }
_ZN2BT21scoped_demangled_nameD2Ev:
   38|  16.3k|  {
   39|  16.3k|    demangle_free(m_p);
   40|  16.3k|  }
_ZN2BT13demangle_freeEPKc:
   63|  16.3k|{
   64|       |  // NOLINTNEXTLINE(cppcoreguidelines-no-malloc,cppcoreguidelines-owning-memory)
   65|  16.3k|  std::free(const_cast<char*>(name));
   66|  16.3k|}

_ZNK2BT9LockedPtrINS_3AnyEEcvbEv:
   52|   171k|  {
   53|   171k|    return ref_ != nullptr;
   54|   171k|  }
_ZNK2BT9LockedPtrINS_3AnyEE3getEv:
   73|   171k|  {
   74|   171k|    return ref_;
   75|   171k|  }
_ZN2BT9LockedPtrINS_3AnyEED2Ev:
   28|   171k|  {
   29|   171k|    if(mutex_ != nullptr)
  ------------------
  |  Branch (29:8): [True: 171k, False: 518]
  ------------------
   30|   171k|    {
   31|   171k|      mutex_->unlock();
   32|   171k|    }
   33|   171k|  }
_ZN2BT9LockedPtrINS_3AnyEEC2Ev:
   20|    518|  LockedPtr() = default;
_ZN2BT9LockedPtrINS_3AnyEEC2EPS1_PSt5mutex:
   22|   171k|  LockedPtr(T* obj, std::mutex* obj_mutex) : ref_(obj), mutex_(obj_mutex)
   23|   171k|  {
   24|   171k|    mutex_->lock();
   25|   171k|  }

_ZNK2BT3Any8isNumberEv:
  346|   308k|{
  347|   308k|  return _any.type() == typeid(int64_t) || _any.type() == typeid(uint64_t) ||
  ------------------
  |  Branch (347:10): [True: 260k, False: 48.9k]
  |  Branch (347:44): [True: 0, False: 48.9k]
  ------------------
  348|  48.9k|         _any.type() == typeid(double);
  ------------------
  |  Branch (348:10): [True: 16.5k, False: 32.3k]
  ------------------
  349|   308k|}
_ZN2BT3AnyC2Ev:
   78|  63.4k|  Any() : _original_type(UndefinedAnyType)
   79|  63.4k|  {}
_ZN2BT3AnyD2Ev:
   81|  5.01M|  ~Any() = default;
_ZNK2BT3Any4castIdEET_v:
  169|   273k|  {
  170|   273k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 273k, False: 201]
  ------------------
  171|   273k|    {
  172|   273k|      return res.value();
  173|   273k|    }
  174|    201|    else
  175|    201|    {
  176|    201|      throw std::runtime_error(res.error());
  177|    201|    }
  178|   273k|  }
_ZNK2BT3Any7tryCastIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  514|   273k|{
  515|   273k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  516|   273k|                                              "can not cast to reference");
  517|       |
  518|   273k|  if(_any.empty())
  ------------------
  |  Branch (518:6): [True: 2, False: 273k]
  ------------------
  519|      2|  {
  520|      2|    throw std::runtime_error("Any::cast failed because it is empty");
  521|      2|  }
  522|       |
  523|   273k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (523:6): [True: 10.8k, False: 262k]
  ------------------
  524|  10.8k|  {
  525|  10.8k|    return linb::any_cast<T>(_any);
  526|  10.8k|  }
  527|       |
  528|       |  // special case when the output is an enum.
  529|       |  // We will try first a int conversion
  530|       |  if constexpr(std::is_enum_v<T>)
  531|       |  {
  532|       |    if(isNumber())
  533|       |    {
  534|       |      return static_cast<T>(convert<int>().value());
  535|       |    }
  536|       |    if(isString())
  537|       |    {
  538|       |      if(auto out = stringToNumber<int64_t>())
  539|       |      {
  540|       |        return static_cast<T>(out.value());
  541|       |      }
  542|       |    }
  543|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  544|       |  }
  545|       |
  546|   262k|  if(isString())
  ------------------
  |  Branch (546:6): [True: 8.04k, False: 254k]
  ------------------
  547|  8.04k|  {
  548|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  549|  8.04k|    {
  550|  8.04k|      if(auto out = stringToNumber<T>())
  ------------------
  |  Branch (550:15): [True: 7.86k, False: 178]
  ------------------
  551|  7.86k|      {
  552|  7.86k|        return out.value();
  553|  7.86k|      }
  554|    178|      else
  555|    178|      {
  556|    178|        return out;
  557|    178|      }
  558|  8.04k|    }
  559|  8.04k|  }
  560|       |
  561|   262k|  if(auto res = convert<T>())
  ------------------
  |  Branch (561:11): [True: 254k, False: 8.06k]
  ------------------
  562|   254k|  {
  563|   254k|    return std::move(res.value());
  564|   254k|  }
  565|  8.06k|  else
  566|  8.06k|  {
  567|  8.06k|    return res;
  568|  8.06k|  }
  569|   262k|}
_ZNK2BT3Any10castedTypeEv:
  200|   358k|  {
  201|   358k|    return _any.type();
  202|   358k|  }
_ZNK2BT3Any8isStringEv:
  141|   389k|  {
  142|   389k|    return _any.type() == typeid(SafeAny::SimpleString);
  143|   389k|  }
_ZNK2BT3Any14stringToNumberIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  422|  8.04k|{
  423|  8.04k|  static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "Expecting a "
  424|  8.04k|                                                                     "numeric type");
  425|       |
  426|  8.04k|  const auto str = linb::any_cast<SafeAny::SimpleString>(_any);
  427|       |#if __cpp_lib_to_chars >= 201611L
  428|       |  T out;
  429|       |  auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out);
  430|       |  if(err == std::errc())
  431|       |  {
  432|       |    return out;
  433|       |  }
  434|       |  else
  435|       |  {
  436|       |    return nonstd::make_unexpected("Any failed string to number conversion");
  437|       |  }
  438|       |#else
  439|  8.04k|  try
  440|  8.04k|  {
  441|       |    if constexpr(std::is_same_v<T, uint16_t>)
  442|       |    {
  443|       |      return std::stoul(str.toStdString());
  444|       |    }
  445|       |    if constexpr(std::is_integral_v<T>)
  446|       |    {
  447|       |      const int64_t val = std::stol(str.toStdString());
  448|       |      Any temp_any(val);
  449|       |      return temp_any.convert<T>();
  450|       |    }
  451|       |    if constexpr(std::is_floating_point_v<T>)
  452|  8.04k|    {
  453|  8.04k|      return std::stod(str.toStdString());
  454|  8.04k|    }
  455|  8.04k|  }
  456|  8.04k|  catch(...)
  457|  8.04k|  {
  458|    178|    return nonstd::make_unexpected("Any failed string to number conversion");
  459|    178|  }
  460|      0|#endif
  461|      0|  return nonstd::make_unexpected("Any conversion from string failed");
  462|  8.04k|}
_ZNK2BT3Any7convertIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  487|   254k|{
  488|   254k|  using SafeAny::details::convertNumber;
  489|   254k|  DST out;
  490|       |
  491|   254k|  const auto& type = _any.type();
  492|       |
  493|   254k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (493:6): [True: 254k, False: 0]
  ------------------
  494|   254k|  {
  495|   254k|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  496|   254k|  }
  497|      0|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (497:11): [True: 0, False: 0]
  ------------------
  498|      0|  {
  499|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  500|      0|  }
  501|      0|  else if(type == typeid(double))
  ------------------
  |  Branch (501:11): [True: 0, False: 0]
  ------------------
  502|      0|  {
  503|      0|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  504|      0|  }
  505|      0|  else
  506|      0|  {
  507|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  508|      0|  }
  509|   254k|  return out;
  510|   254k|}
_ZNK2BT3Any4typeEv:
  194|  16.4k|  {
  195|  16.4k|    return _original_type;
  196|  16.4k|  }
_ZN2BT3AnyC2IiEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  118|  5.42k|    : _any(int64_t(value)), _original_type(typeid(T))
  119|  5.42k|  {}
_ZN2BT3AnyaSERKS0_:
  329|   158k|{
  330|   158k|  if(this != &other)
  ------------------
  |  Branch (330:6): [True: 158k, False: 0]
  ------------------
  331|   158k|  {
  332|   158k|    this->_any = other._any;
  333|   158k|    this->_original_type = other._original_type;
  334|   158k|  }
  335|   158k|  return *this;
  336|   158k|}
_ZN2BT3AnyaSEOS0_:
  339|  40.5k|{
  340|  40.5k|  this->_any = std::move(other._any);
  341|  40.5k|  this->_original_type = other._original_type;
  342|  40.5k|  return *this;
  343|  40.5k|}
_ZNK2BT3Any8copyIntoERS0_:
  357|  10.1k|{
  358|  10.1k|  if(dst.empty())
  ------------------
  |  Branch (358:6): [True: 0, False: 10.1k]
  ------------------
  359|      0|  {
  360|      0|    dst = *this;
  361|      0|    return;
  362|      0|  }
  363|       |
  364|  10.1k|  const auto& dst_type = dst.castedType();
  365|       |
  366|  10.1k|  if((castedType() == dst_type) || (isString() && dst.isString()))
  ------------------
  |  Branch (366:6): [True: 9.00k, False: 1.11k]
  |  Branch (366:37): [True: 8, False: 1.10k]
  |  Branch (366:51): [True: 0, False: 8]
  ------------------
  367|  9.00k|  {
  368|  9.00k|    dst._any = _any;
  369|  9.00k|  }
  370|  1.11k|  else if(isNumber() && dst.isNumber())
  ------------------
  |  Branch (370:11): [True: 1.10k, False: 8]
  |  Branch (370:25): [True: 1.05k, False: 50]
  ------------------
  371|  1.05k|  {
  372|  1.05k|    if(dst_type == typeid(int64_t))
  ------------------
  |  Branch (372:8): [True: 857, False: 198]
  ------------------
  373|    857|    {
  374|    857|      dst._any = cast<int64_t>();
  375|    857|    }
  376|    198|    else if(dst_type == typeid(uint64_t))
  ------------------
  |  Branch (376:13): [True: 0, False: 198]
  ------------------
  377|      0|    {
  378|      0|      dst._any = cast<uint64_t>();
  379|      0|    }
  380|    198|    else if(dst_type == typeid(double))
  ------------------
  |  Branch (380:13): [True: 198, False: 0]
  ------------------
  381|    198|    {
  382|    198|      dst._any = cast<double>();
  383|    198|    }
  384|      0|    else
  385|      0|    {
  386|      0|      throw std::runtime_error("Any::copyInto fails");
  387|      0|    }
  388|  1.05k|  }
  389|     58|  else
  390|     58|  {
  391|     58|    throw std::runtime_error("Any::copyInto fails");
  392|     58|  }
  393|  10.1k|}
_ZNK2BT3Any5emptyEv:
  205|   351k|  {
  206|   351k|    return _any.empty();
  207|   351k|  }
_ZNK2BT3Any4castIlEET_v:
  169|  3.38k|  {
  170|  3.38k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 3.36k, False: 11]
  ------------------
  171|  3.36k|    {
  172|  3.36k|      return res.value();
  173|  3.36k|    }
  174|     11|    else
  175|     11|    {
  176|     11|      throw std::runtime_error(res.error());
  177|     11|    }
  178|  3.38k|  }
_ZNK2BT3Any7tryCastIlEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  514|  3.38k|{
  515|  3.38k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  516|  3.38k|                                              "can not cast to reference");
  517|       |
  518|  3.38k|  if(_any.empty())
  ------------------
  |  Branch (518:6): [True: 0, False: 3.38k]
  ------------------
  519|      0|  {
  520|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  521|      0|  }
  522|       |
  523|  3.38k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (523:6): [True: 1.06k, False: 2.31k]
  ------------------
  524|  1.06k|  {
  525|  1.06k|    return linb::any_cast<T>(_any);
  526|  1.06k|  }
  527|       |
  528|       |  // special case when the output is an enum.
  529|       |  // We will try first a int conversion
  530|       |  if constexpr(std::is_enum_v<T>)
  531|       |  {
  532|       |    if(isNumber())
  533|       |    {
  534|       |      return static_cast<T>(convert<int>().value());
  535|       |    }
  536|       |    if(isString())
  537|       |    {
  538|       |      if(auto out = stringToNumber<int64_t>())
  539|       |      {
  540|       |        return static_cast<T>(out.value());
  541|       |      }
  542|       |    }
  543|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  544|       |  }
  545|       |
  546|  2.31k|  if(isString())
  ------------------
  |  Branch (546:6): [True: 0, False: 2.31k]
  ------------------
  547|      0|  {
  548|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  549|      0|    {
  550|      0|      if(auto out = stringToNumber<T>())
  ------------------
  |  Branch (550:15): [True: 0, False: 0]
  ------------------
  551|      0|      {
  552|      0|        return out.value();
  553|      0|      }
  554|      0|      else
  555|      0|      {
  556|      0|        return out;
  557|      0|      }
  558|      0|    }
  559|      0|  }
  560|       |
  561|  2.31k|  if(auto res = convert<T>())
  ------------------
  |  Branch (561:11): [True: 2.30k, False: 11]
  ------------------
  562|  2.30k|  {
  563|  2.30k|    return std::move(res.value());
  564|  2.30k|  }
  565|     11|  else
  566|     11|  {
  567|     11|    return res;
  568|     11|  }
  569|  2.31k|}
_ZN2BT3AnyC2IlEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  118|  1.36M|    : _any(int64_t(value)), _original_type(typeid(T))
  119|  1.36M|  {}
_ZNK2BT3Any7convertIlEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  487|  2.31k|{
  488|  2.31k|  using SafeAny::details::convertNumber;
  489|  2.31k|  DST out;
  490|       |
  491|  2.31k|  const auto& type = _any.type();
  492|       |
  493|  2.31k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (493:6): [True: 0, False: 2.31k]
  ------------------
  494|      0|  {
  495|      0|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  496|      0|  }
  497|  2.31k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (497:11): [True: 0, False: 2.31k]
  ------------------
  498|      0|  {
  499|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  500|      0|  }
  501|  2.31k|  else if(type == typeid(double))
  ------------------
  |  Branch (501:11): [True: 2.31k, False: 0]
  ------------------
  502|  2.31k|  {
  503|  2.31k|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  504|  2.31k|  }
  505|      0|  else
  506|      0|  {
  507|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  508|      0|  }
  509|  2.31k|  return out;
  510|  2.31k|}
_ZN2BT3AnyC2ERKd:
   90|   162k|  explicit Any(const double& value) : _any(value), _original_type(typeid(double))
   91|   162k|  {}
_ZN2BT3AnyC2IbEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  118|  5.42k|    : _any(int64_t(value)), _original_type(typeid(T))
  119|  5.42k|  {}
_ZN2BT3AnyC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  100|   101k|    : _any(SafeAny::SimpleString(str)), _original_type(typeid(std::string))
  101|   101k|  {}
_ZN2BT3AnyC2ERKS0_:
   83|  1.81M|  Any(const Any& other) : _any(other._any), _original_type(other._original_type)
   84|  1.81M|  {}
_ZN2BT3AnyC2EOS0_:
   87|  1.45M|    : _any(std::move(other._any)), _original_type(other._original_type)
   88|  1.45M|  {}
_ZN2BT3AnyC2ERKSt10type_index:
  121|  31.6k|  Any(const std::type_index& type) : _original_type(type)
  122|  31.6k|  {}
_ZNK2BT3Any4castINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEET_v:
  169|  41.1k|  {
  170|  41.1k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 41.1k, False: 0]
  ------------------
  171|  41.1k|    {
  172|  41.1k|      return res.value();
  173|  41.1k|    }
  174|      0|    else
  175|      0|    {
  176|      0|      throw std::runtime_error(res.error());
  177|      0|    }
  178|  41.1k|  }
_ZNK2BT3Any7tryCastINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEN6nonstd13expected_lite8expectedIT_S7_EEv:
  514|  41.1k|{
  515|  41.1k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  516|  41.1k|                                              "can not cast to reference");
  517|       |
  518|  41.1k|  if(_any.empty())
  ------------------
  |  Branch (518:6): [True: 0, False: 41.1k]
  ------------------
  519|      0|  {
  520|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  521|      0|  }
  522|       |
  523|  41.1k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (523:6): [True: 0, False: 41.1k]
  ------------------
  524|      0|  {
  525|      0|    return linb::any_cast<T>(_any);
  526|      0|  }
  527|       |
  528|       |  // special case when the output is an enum.
  529|       |  // We will try first a int conversion
  530|       |  if constexpr(std::is_enum_v<T>)
  531|       |  {
  532|       |    if(isNumber())
  533|       |    {
  534|       |      return static_cast<T>(convert<int>().value());
  535|       |    }
  536|       |    if(isString())
  537|       |    {
  538|       |      if(auto out = stringToNumber<int64_t>())
  539|       |      {
  540|       |        return static_cast<T>(out.value());
  541|       |      }
  542|       |    }
  543|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  544|       |  }
  545|       |
  546|  41.1k|  if(isString())
  ------------------
  |  Branch (546:6): [True: 37.7k, False: 3.40k]
  ------------------
  547|  37.7k|  {
  548|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  549|       |    {
  550|       |      if(auto out = stringToNumber<T>())
  551|       |      {
  552|       |        return out.value();
  553|       |      }
  554|       |      else
  555|       |      {
  556|       |        return out;
  557|       |      }
  558|       |    }
  559|  37.7k|  }
  560|       |
  561|  41.1k|  if(auto res = convert<T>())
  ------------------
  |  Branch (561:11): [True: 41.1k, False: 0]
  ------------------
  562|  41.1k|  {
  563|  41.1k|    return std::move(res.value());
  564|  41.1k|  }
  565|      0|  else
  566|      0|  {
  567|      0|    return res;
  568|      0|  }
  569|  41.1k|}
_ZNK2BT3Any7convertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEN6nonstd13expected_lite8expectedIT_S7_EEPNSt9enable_ifIXsr3std7is_sameISB_S7_EE5valueEvE4typeE:
  397|  41.1k|{
  398|  41.1k|  const auto& type = _any.type();
  399|       |
  400|  41.1k|  if(type == typeid(SafeAny::SimpleString))
  ------------------
  |  Branch (400:6): [True: 37.7k, False: 3.40k]
  ------------------
  401|  37.7k|  {
  402|  37.7k|    return linb::any_cast<SafeAny::SimpleString>(_any).toStdString();
  403|  37.7k|  }
  404|  3.40k|  else if(type == typeid(int64_t))
  ------------------
  |  Branch (404:11): [True: 970, False: 2.43k]
  ------------------
  405|    970|  {
  406|    970|    return std::to_string(linb::any_cast<int64_t>(_any));
  407|    970|  }
  408|  2.43k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (408:11): [True: 0, False: 2.43k]
  ------------------
  409|      0|  {
  410|      0|    return std::to_string(linb::any_cast<uint64_t>(_any));
  411|      0|  }
  412|  2.43k|  else if(type == typeid(double))
  ------------------
  |  Branch (412:11): [True: 2.43k, False: 0]
  ------------------
  413|  2.43k|  {
  414|  2.43k|    return std::to_string(linb::any_cast<double>(_any));
  415|  2.43k|  }
  416|       |
  417|      0|  return nonstd::make_unexpected(errorMsg<DST>());
  418|  41.1k|}
_ZNK2BT3Any6isTypeIN7SafeAny12SimpleStringEEEbv:
  148|    673|  {
  149|    673|    return _original_type == typeid(T);
  150|    673|  }
_ZNK2BT3Any4castIN7SafeAny12SimpleStringEEET_v:
  169|  17.4k|  {
  170|  17.4k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 17.4k, False: 0]
  ------------------
  171|  17.4k|    {
  172|  17.4k|      return res.value();
  173|  17.4k|    }
  174|      0|    else
  175|      0|    {
  176|      0|      throw std::runtime_error(res.error());
  177|      0|    }
  178|  17.4k|  }
_ZNK2BT3Any7tryCastIN7SafeAny12SimpleStringEEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  514|  17.4k|{
  515|  17.4k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  516|  17.4k|                                              "can not cast to reference");
  517|       |
  518|  17.4k|  if(_any.empty())
  ------------------
  |  Branch (518:6): [True: 0, False: 17.4k]
  ------------------
  519|      0|  {
  520|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  521|      0|  }
  522|       |
  523|  17.4k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (523:6): [True: 17.4k, False: 0]
  ------------------
  524|  17.4k|  {
  525|  17.4k|    return linb::any_cast<T>(_any);
  526|  17.4k|  }
  527|       |
  528|       |  // special case when the output is an enum.
  529|       |  // We will try first a int conversion
  530|       |  if constexpr(std::is_enum_v<T>)
  531|       |  {
  532|       |    if(isNumber())
  533|       |    {
  534|       |      return static_cast<T>(convert<int>().value());
  535|       |    }
  536|       |    if(isString())
  537|       |    {
  538|       |      if(auto out = stringToNumber<int64_t>())
  539|       |      {
  540|       |        return static_cast<T>(out.value());
  541|       |      }
  542|       |    }
  543|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  544|       |  }
  545|       |
  546|      0|  if(isString())
  ------------------
  |  Branch (546:6): [True: 0, False: 0]
  ------------------
  547|      0|  {
  548|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  549|       |    {
  550|       |      if(auto out = stringToNumber<T>())
  551|       |      {
  552|       |        return out.value();
  553|       |      }
  554|       |      else
  555|       |      {
  556|       |        return out;
  557|       |      }
  558|       |    }
  559|      0|  }
  560|       |
  561|      0|  if(auto res = convert<T>())
  ------------------
  |  Branch (561:11): [True: 0, False: 0]
  ------------------
  562|      0|  {
  563|      0|    return std::move(res.value());
  564|      0|  }
  565|      0|  else
  566|      0|  {
  567|      0|    return res;
  568|      0|  }
  569|      0|}
_ZNK2BT3Any4castIbEET_v:
  169|  2.56k|  {
  170|  2.56k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 2.43k, False: 137]
  ------------------
  171|  2.43k|    {
  172|  2.43k|      return res.value();
  173|  2.43k|    }
  174|    137|    else
  175|    137|    {
  176|    137|      throw std::runtime_error(res.error());
  177|    137|    }
  178|  2.56k|  }
_ZNK2BT3Any7tryCastIbEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  514|  2.56k|{
  515|  2.56k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  516|  2.56k|                                              "can not cast to reference");
  517|       |
  518|  2.56k|  if(_any.empty())
  ------------------
  |  Branch (518:6): [True: 0, False: 2.56k]
  ------------------
  519|      0|  {
  520|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  521|      0|  }
  522|       |
  523|  2.56k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (523:6): [True: 0, False: 2.56k]
  ------------------
  524|      0|  {
  525|      0|    return linb::any_cast<T>(_any);
  526|      0|  }
  527|       |
  528|       |  // special case when the output is an enum.
  529|       |  // We will try first a int conversion
  530|       |  if constexpr(std::is_enum_v<T>)
  531|       |  {
  532|       |    if(isNumber())
  533|       |    {
  534|       |      return static_cast<T>(convert<int>().value());
  535|       |    }
  536|       |    if(isString())
  537|       |    {
  538|       |      if(auto out = stringToNumber<int64_t>())
  539|       |      {
  540|       |        return static_cast<T>(out.value());
  541|       |      }
  542|       |    }
  543|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  544|       |  }
  545|       |
  546|  2.56k|  if(isString())
  ------------------
  |  Branch (546:6): [True: 0, False: 2.56k]
  ------------------
  547|      0|  {
  548|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  549|       |    {
  550|       |      if(auto out = stringToNumber<T>())
  551|       |      {
  552|       |        return out.value();
  553|       |      }
  554|       |      else
  555|       |      {
  556|       |        return out;
  557|       |      }
  558|       |    }
  559|      0|  }
  560|       |
  561|  2.56k|  if(auto res = convert<T>())
  ------------------
  |  Branch (561:11): [True: 2.43k, False: 137]
  ------------------
  562|  2.43k|  {
  563|  2.43k|    return std::move(res.value());
  564|  2.43k|  }
  565|    137|  else
  566|    137|  {
  567|    137|    return res;
  568|    137|  }
  569|  2.56k|}
_ZNK2BT3Any7convertIbEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  487|  2.56k|{
  488|  2.56k|  using SafeAny::details::convertNumber;
  489|  2.56k|  DST out;
  490|       |
  491|  2.56k|  const auto& type = _any.type();
  492|       |
  493|  2.56k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (493:6): [True: 1.49k, False: 1.06k]
  ------------------
  494|  1.49k|  {
  495|  1.49k|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  496|  1.49k|  }
  497|  1.06k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (497:11): [True: 0, False: 1.06k]
  ------------------
  498|      0|  {
  499|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  500|      0|  }
  501|  1.06k|  else if(type == typeid(double))
  ------------------
  |  Branch (501:11): [True: 1.06k, False: 0]
  ------------------
  502|  1.06k|  {
  503|  1.06k|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  504|  1.06k|  }
  505|      0|  else
  506|      0|  {
  507|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  508|      0|  }
  509|  2.56k|  return out;
  510|  2.56k|}

_ZN7SafeAny12SimpleStringC2ERKS0_:
   33|   402k|  SimpleString(const SimpleString& other) : SimpleString(other.data(), other.size())
   34|   402k|  {}
_ZNK7SafeAny12SimpleString4dataEv:
   87|   461k|  {
   88|   461k|    if(isSOO())
  ------------------
  |  Branch (88:8): [True: 360k, False: 100k]
  ------------------
   89|   360k|    {
   90|   360k|      return _storage.soo.data;
   91|   360k|    }
   92|   100k|    else
   93|   100k|    {
   94|   100k|      return _storage.str.data;
   95|   100k|    }
   96|   461k|  }
_ZNK7SafeAny12SimpleString5isSOOEv:
  155|  1.75M|  {
  156|  1.75M|    return (_storage.soo.capacity_left & IS_LONG_BIT) == 0;
  157|  1.75M|  }
_ZNK7SafeAny12SimpleString4sizeEv:
   99|   515k|  {
  100|   515k|    if(isSOO())
  ------------------
  |  Branch (100:8): [True: 389k, False: 125k]
  ------------------
  101|   389k|    {
  102|   389k|      return CAPACITY - _storage.soo.capacity_left;
  103|   389k|    }
  104|   125k|    else
  105|   125k|    {
  106|   125k|      return _storage.str.size & LONG_MASK;
  107|   125k|    }
  108|   515k|  }
_ZN7SafeAny12SimpleStringC2EPKcm:
   64|   503k|  {
   65|   503k|    createImpl(input_data, size);
   66|   503k|  }
_ZN7SafeAny12SimpleString10createImplEPKcm:
  184|   503k|  {
  185|   503k|    if(size > MAX_SIZE)
  ------------------
  |  Branch (185:8): [True: 13, False: 503k]
  ------------------
  186|     13|    {
  187|     13|      throw std::invalid_argument("size too large for a simple string");
  188|     13|    }
  189|       |
  190|   503k|    if(size > CAPACITY)
  ------------------
  |  Branch (190:8): [True: 97.0k, False: 406k]
  ------------------
  191|  97.0k|    {
  192|  97.0k|      _storage.str.size = size;
  193|  97.0k|      _storage.soo.capacity_left = IS_LONG_BIT;
  194|  97.0k|      _storage.str.data = new char[size + 1];  // NOLINT(cppcoreguidelines-owning-memory)
  195|  97.0k|      std::memcpy(_storage.str.data, input_data, size);
  196|  97.0k|      _storage.str.data[size] = '\0';
  197|  97.0k|    }
  198|   406k|    else
  199|   406k|    {
  200|   406k|      _storage.soo.capacity_left = uint8_t(CAPACITY - size);
  201|   406k|      if(size > 0)
  ------------------
  |  Branch (201:10): [True: 187k, False: 219k]
  ------------------
  202|   187k|      {
  203|   187k|        std::memcpy(_storage.soo.data, input_data, size);
  204|   187k|      }
  205|   406k|      if(size < CAPACITY)
  ------------------
  |  Branch (205:10): [True: 404k, False: 2.44k]
  ------------------
  206|   404k|      {
  207|   404k|        _storage.soo.data[size] = '\0';
  208|   404k|      }
  209|   406k|    }
  210|   503k|  }
_ZNK7SafeAny12SimpleString11toStdStringB5cxx11Ev:
   78|  45.7k|  {
   79|  45.7k|    return size() > 0 ? std::string(data(), size()) : std::string();
  ------------------
  |  Branch (79:12): [True: 42.1k, False: 3.65k]
  ------------------
   80|  45.7k|  }
_ZN7SafeAny12SimpleStringD2Ev:
   69|   777k|  {
   70|   777k|    if(!isSOO())
  ------------------
  |  Branch (70:8): [True: 97.0k, False: 680k]
  ------------------
   71|  97.0k|    {
   72|  97.0k|      delete[] _storage.str.data;
   73|  97.0k|    }
   74|   777k|    _storage.soo.capacity_left = CAPACITY;
   75|   777k|  }
_ZN7SafeAny12SimpleStringC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   27|   101k|  SimpleString(const std::string& str) : SimpleString(str.data(), str.size())
   28|   101k|  {}
_ZN7SafeAny12SimpleStringC2EOS0_:
   46|   273k|  SimpleString(SimpleString&& other) noexcept : SimpleString()
   47|   273k|  {
   48|   273k|    std::swap(_storage, other._storage);
   49|   273k|  }
_ZN7SafeAny12SimpleStringC2Ev:
   22|   273k|  {
   23|   273k|    _storage.soo.capacity_left = CAPACITY;
   24|   273k|    _storage.soo.data[0] = '\0';
   25|   273k|  }
_ZNK7SafeAny12SimpleStringeqERKS0_:
  111|  2.11k|  {
  112|  2.11k|    const size_t N = size();
  113|  2.11k|    return other.size() == N && std::strncmp(data(), other.data(), N) == 0;
  ------------------
  |  Branch (113:12): [True: 1.59k, False: 528]
  |  Branch (113:33): [True: 935, False: 655]
  ------------------
  114|  2.11k|  }
_ZNK7SafeAny12SimpleStringleERKS0_:
  123|  1.61k|  {
  124|  1.61k|    return !(*this > other);
  125|  1.61k|  }
_ZNK7SafeAny12SimpleStringgeERKS0_:
  128|  1.82k|  {
  129|  1.82k|    return !(*this < other);
  130|  1.82k|  }
_ZNK7SafeAny12SimpleStringltERKS0_:
  133|  3.63k|  {
  134|  3.63k|    const size_t min_size = std::min(size(), other.size());
  135|  3.63k|    int cmp = std::memcmp(data(), other.data(), min_size);
  136|  3.63k|    if(cmp != 0)
  ------------------
  |  Branch (136:8): [True: 1.40k, False: 2.22k]
  ------------------
  137|  1.40k|    {
  138|  1.40k|      return cmp < 0;
  139|  1.40k|    }
  140|  2.22k|    return size() < other.size();
  141|  3.63k|  }
_ZNK7SafeAny12SimpleStringgtERKS0_:
  144|  2.97k|  {
  145|  2.97k|    const size_t min_size = std::min(size(), other.size());
  146|  2.97k|    int cmp = std::memcmp(data(), other.data(), min_size);
  147|  2.97k|    if(cmp != 0)
  ------------------
  |  Branch (147:8): [True: 1.42k, False: 1.55k]
  ------------------
  148|  1.42k|    {
  149|  1.42k|      return cmp > 0;
  150|  1.42k|    }
  151|  1.55k|    return size() > other.size();
  152|  2.97k|  }

_ZN2BT16strings_internal9CatPiecesB5cxx11ESt16initializer_listISt17basic_string_viewIcSt11char_traitsIcEEE:
   38|  5.58k|{
   39|  5.58k|  std::string out;
   40|  5.58k|  AppendPieces(&out, std::move(pieces));
   41|  5.58k|  return out;
   42|  5.58k|}
_ZN2BT16strings_internal12AppendPiecesEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt16initializer_listISt17basic_string_viewIcS4_EE:
   24|  5.58k|{
   25|  5.58k|  size_t size = 0;
   26|  5.58k|  for(const auto& piece : pieces)
  ------------------
  |  Branch (26:25): [True: 24.2k, False: 5.58k]
  ------------------
   27|  24.2k|  {
   28|  24.2k|    size += piece.size();
   29|  24.2k|  }
   30|  5.58k|  dest->reserve(dest->size() + size);
   31|  5.58k|  for(const auto& piece : pieces)
  ------------------
  |  Branch (31:25): [True: 24.2k, False: 5.58k]
  ------------------
   32|  24.2k|  {
   33|  24.2k|    dest->append(piece.data(), piece.size());
   34|  24.2k|  }
   35|  5.58k|}
_ZN2BT6StrCatB5cxx11ERKSt17basic_string_viewIcSt11char_traitsIcEE:
   52|  5.75k|{
   53|  5.75k|  return std::string(a.data(), a.size());
   54|  5.75k|}
_ZN2BT6StrCatB5cxx11ERKSt17basic_string_viewIcSt11char_traitsIcEES5_:
   57|    518|{
   58|    518|  return strings_internal::CatPieces({ a, b });
   59|    518|}
_ZN2BT6StrCatB5cxx11ERKSt17basic_string_viewIcSt11char_traitsIcEES5_S5_:
   63|     71|{
   64|     71|  return strings_internal::CatPieces({ a, b, c });
   65|     71|}
_ZN2BT6StrCatIJA8_cSt17basic_string_viewIcSt11char_traitsIcEEA3_cEEENSt7__cxx1112basic_stringIcS4_SaIcEEERKS5_SC_SC_SC_DpRKT_:
   72|    354|{
   73|    354|  return strings_internal::CatPieces(
   74|    354|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|    354|}
_ZN2BT6StrCatIJEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS4_ESA_SA_SA_DpRKT_:
   72|  2.71k|{
   73|  2.71k|  return strings_internal::CatPieces(
   74|  2.71k|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|  2.71k|}
_ZN2BT6StrCatIJA3_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|  1.74k|{
   73|  1.74k|  return strings_internal::CatPieces(
   74|  1.74k|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|  1.74k|}
_ZN2BT6StrCatIJA21_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|     73|{
   73|     73|  return strings_internal::CatPieces(
   74|     73|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|     73|}
_ZN2BT6StrCatIJA4_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|     55|{
   73|     55|  return strings_internal::CatPieces(
   74|     55|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|     55|}
_ZN2BT6StrCatIJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEA2_cEEES6_RKSt17basic_string_viewIcS4_ESB_SB_SB_DpRKT_:
   72|     55|{
   73|     55|  return strings_internal::CatPieces(
   74|     55|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|     55|}

_ZN2BT17convertFromStringIdEET_St17basic_string_viewIcSt11char_traitsIcEE:
  201|  4.96k|{
  202|       |#if __cpp_lib_to_chars >= 201611L
  203|       |  // from_chars is locale-independent and thread-safe
  204|       |  double result = 0;
  205|       |  const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
  206|       |  if(ec != std::errc())
  207|       |  {
  208|       |    throw RuntimeError(StrCat("Can't convert string [", str, "] to double"));
  209|       |  }
  210|       |  return result;
  211|       |#else
  212|       |  // Fallback: stod is locale-dependent, so force "C" locale.
  213|       |  // See issue #120.  Note: setlocale is not thread-safe.
  214|  4.96k|  const std::string old_locale = setlocale(LC_NUMERIC, nullptr);
  215|  4.96k|  std::ignore = setlocale(LC_NUMERIC, "C");
  216|  4.96k|  const std::string str_copy(str.data(), str.size());
  217|  4.96k|  const double val = std::stod(str_copy);
  218|       |  std::ignore = setlocale(LC_NUMERIC, old_locale.c_str());
  219|  4.96k|  return val;
  220|  4.96k|#endif
  221|  4.96k|}
_ZNK2BT8TypeInfo4typeEv:
  438|  40.4k|{
  439|  40.4k|  return type_info_;
  440|  40.4k|}
_ZN2BT9StartWithESt17basic_string_viewIcSt11char_traitsIcEEc:
  592|   404k|{
  593|   404k|  return str.size() >= 1 && str[0] == prefix;
  ------------------
  |  Branch (593:10): [True: 246k, False: 157k]
  |  Branch (593:29): [True: 167k, False: 79.1k]
  ------------------
  594|   404k|}

_ZN2BT10Blackboard12getAnyLockedERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   25|   171k|{
   26|   171k|  if(auto entry = getEntry(key))
  ------------------
  |  Branch (26:11): [True: 171k, False: 518]
  ------------------
   27|   171k|  {
   28|   171k|    return AnyPtrLocked(&entry->value, &entry->entry_mutex);
   29|   171k|  }
   30|    518|  return {};
   31|   171k|}
_ZNK2BT10Blackboard8getEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   55|   372k|{
   56|       |  // special syntax: "@" will always refer to the root BB
   57|   372k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (57:6): [True: 164k, False: 208k]
  ------------------
   58|   164k|  {
   59|   164k|    return rootBlackboard()->getEntry(key.substr(1, key.size() - 1));
   60|   164k|  }
   61|       |
   62|   208k|  {
   63|   208k|    const std::shared_lock<std::shared_mutex> storage_lock(storage_mutex_);
   64|   208k|    auto it = storage_.find(key);
   65|   208k|    if(it != storage_.end())
  ------------------
  |  Branch (65:8): [True: 197k, False: 10.5k]
  ------------------
   66|   197k|    {
   67|   197k|      return it->second;
   68|   197k|    }
   69|   208k|  }
   70|       |  // not found. Try autoremapping
   71|  10.5k|  if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (71:11): [True: 0, False: 10.5k]
  ------------------
   72|      0|  {
   73|      0|    auto remap_it = internal_to_external_.find(key);
   74|      0|    if(remap_it != internal_to_external_.cend())
  ------------------
  |  Branch (74:8): [True: 0, False: 0]
  ------------------
   75|      0|    {
   76|      0|      auto const& new_key = remap_it->second;
   77|      0|      return parent->getEntry(new_key);
   78|      0|    }
   79|      0|    if(autoremapping_ && !IsPrivateKey(key))
  ------------------
  |  Branch (79:8): [True: 0, False: 0]
  |  Branch (79:26): [True: 0, False: 0]
  ------------------
   80|      0|    {
   81|      0|      return parent->getEntry(key);
   82|      0|    }
   83|      0|  }
   84|  10.5k|  return {};
   85|  10.5k|}
_ZN2BT10Blackboard8getEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   88|   208k|{
   89|   208k|  return static_cast<const Blackboard&>(*this).getEntry(key);
   90|   208k|}
_ZN2BT10Blackboard9entryInfoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   93|    828|{
   94|    828|  auto entry = getEntry(key);
   95|    828|  return (!entry) ? nullptr : &(entry->info);
  ------------------
  |  Branch (95:10): [True: 0, False: 828]
  ------------------
   96|    828|}
_ZN2BT10Blackboard11createEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_8TypeInfoE:
  165|  9.91k|{
  166|  9.91k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (166:6): [True: 3.01k, False: 6.89k]
  ------------------
  167|  3.01k|  {
  168|  3.01k|    if(key.find('@', 1) != std::string::npos)
  ------------------
  |  Branch (168:8): [True: 0, False: 3.01k]
  ------------------
  169|      0|    {
  170|      0|      throw LogicError("Character '@' used multiple times in the key");
  171|      0|    }
  172|  3.01k|    rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
  173|  3.01k|  }
  174|  6.89k|  else
  175|  6.89k|  {
  176|  6.89k|    createEntryImpl(key, info);
  177|  6.89k|  }
  178|  9.91k|}
_ZN2BT10Blackboard15createEntryImplERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_8TypeInfoE:
  284|  31.6k|{
  285|  31.6k|  const std::unique_lock storage_lock(storage_mutex_);
  286|       |  // This function might be called recursively, when we do remapping, because we move
  287|       |  // to the top scope to find already existing  entries
  288|       |
  289|       |  // search if exists already
  290|  31.6k|  auto storage_it = storage_.find(key);
  291|  31.6k|  if(storage_it != storage_.end())
  ------------------
  |  Branch (291:6): [True: 0, False: 31.6k]
  ------------------
  292|      0|  {
  293|      0|    const auto& prev_info = storage_it->second->info;
  294|      0|    if(prev_info.type() != info.type() && prev_info.isStronglyTyped() &&
  ------------------
  |  Branch (294:8): [True: 0, False: 0]
  |  Branch (294:43): [True: 0, False: 0]
  ------------------
  295|      0|       info.isStronglyTyped())
  ------------------
  |  Branch (295:8): [True: 0, False: 0]
  ------------------
  296|      0|    {
  297|      0|      auto msg = StrCat("Blackboard entry [", key,
  298|      0|                        "]: once declared, the type of a port"
  299|      0|                        " shall not change. Previously declared type [",
  300|      0|                        BT::demangle(prev_info.type()), "], current type [",
  301|      0|                        BT::demangle(info.type()), "]");
  302|       |
  303|      0|      throw LogicError(msg);
  304|      0|    }
  305|      0|    return storage_it->second;
  306|      0|  }
  307|       |
  308|       |  // manual remapping first
  309|  31.6k|  auto remapping_it = internal_to_external_.find(key);
  310|  31.6k|  if(remapping_it != internal_to_external_.end())
  ------------------
  |  Branch (310:6): [True: 0, False: 31.6k]
  ------------------
  311|      0|  {
  312|      0|    const auto& remapped_key = remapping_it->second;
  313|      0|    if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (313:13): [True: 0, False: 0]
  ------------------
  314|      0|    {
  315|      0|      return parent->createEntryImpl(remapped_key, info);
  316|      0|    }
  317|      0|    throw RuntimeError("Missing parent blackboard");
  318|      0|  }
  319|       |  // autoremapping second (excluding private keys)
  320|  31.6k|  if(autoremapping_ && !IsPrivateKey(key))
  ------------------
  |  Branch (320:6): [True: 0, False: 31.6k]
  |  Branch (320:24): [True: 0, False: 0]
  ------------------
  321|      0|  {
  322|      0|    if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (322:13): [True: 0, False: 0]
  ------------------
  323|      0|    {
  324|      0|      return parent->createEntryImpl(key, info);
  325|      0|    }
  326|      0|    throw RuntimeError("Missing parent blackboard");
  327|      0|  }
  328|       |  // not remapped, not found. Create locally.
  329|       |
  330|  31.6k|  auto entry = std::make_shared<Entry>(info);
  331|       |  // even if empty, let's assign to it a default type
  332|  31.6k|  entry->value = Any(info.type());
  333|  31.6k|  storage_.insert({ key, entry });
  334|  31.6k|  return entry;
  335|  31.6k|}
_ZN2BT10Blackboard14rootBlackboardEv:
  374|  3.01k|{
  375|  3.01k|  auto bb = static_cast<const Blackboard&>(*this).rootBlackboard();
  376|       |  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
  377|  3.01k|  return const_cast<Blackboard*>(bb);
  378|  3.01k|}
_ZNK2BT10Blackboard14rootBlackboardEv:
  381|   167k|{
  382|   167k|  const Blackboard* bb = this;
  383|   167k|  Blackboard::Ptr prev = parent_bb_.lock();
  384|   167k|  while(prev)
  ------------------
  |  Branch (384:9): [True: 0, False: 167k]
  ------------------
  385|      0|  {
  386|      0|    bb = prev.get();
  387|      0|    prev = bb->parent_bb_.lock();
  388|      0|  }
  389|   167k|  return bb;
  390|   167k|}

_ZN2BT9Scripting15parseStatementsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  422|  11.9k|{
  423|  11.9k|  auto tokens = tokenize(script);
  424|  11.9k|  ScriptParser parser(std::move(tokens));
  425|  11.9k|  return parser.parseAll();
  426|  11.9k|}
_ZN2BT11ParseScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  433|  6.56k|{
  434|  6.56k|  try
  435|  6.56k|  {
  436|  6.56k|    auto exprs = Scripting::parseStatements(script);
  437|  6.56k|    if(exprs.empty())
  ------------------
  |  Branch (437:8): [True: 46, False: 6.51k]
  ------------------
  438|     46|    {
  439|     46|      return nonstd::make_unexpected("Empty Script");
  440|     46|    }
  441|  6.51k|    return [exprs = std::move(exprs), script](Ast::Environment& env) {
  442|  6.51k|      try
  443|  6.51k|      {
  444|  6.51k|        for(size_t i = 0; i < exprs.size() - 1; ++i)
  445|  6.51k|        {
  446|  6.51k|          exprs[i]->evaluate(env);
  447|  6.51k|        }
  448|  6.51k|        return exprs.back()->evaluate(env);
  449|  6.51k|      }
  450|  6.51k|      catch(RuntimeError& err)
  451|  6.51k|      {
  452|  6.51k|        throw RuntimeError(StrCat("Error in script [", script, "]\n", err.what()));
  453|  6.51k|      }
  454|  6.51k|    };
  455|  6.56k|  }
  456|  6.56k|  catch(RuntimeError& err)
  457|  6.56k|  {
  458|  2.57k|    return nonstd::make_unexpected(err.what());
  459|  2.57k|  }
  460|  6.56k|}
_ZN2BT21ParseScriptAndExecuteERNS_3Ast11EnvironmentERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  463|  5.25k|{
  464|  5.25k|  auto executor = ParseScript(script);
  465|  5.25k|  if(executor)
  ------------------
  |  Branch (465:6): [True: 3.94k, False: 1.31k]
  ------------------
  466|  3.94k|  {
  467|  3.94k|    try
  468|  3.94k|    {
  469|  3.94k|      return executor.value()(env);
  470|  3.94k|    }
  471|  3.94k|    catch(RuntimeError& err)
  472|  3.94k|    {
  473|    943|      return nonstd::make_unexpected(err.what());
  474|    943|    }
  475|  3.94k|  }
  476|  1.31k|  return nonstd::make_unexpected(executor.error());
  477|  5.25k|}
_ZN2BT14ValidateScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  480|  5.42k|{
  481|  5.42k|  try
  482|  5.42k|  {
  483|  5.42k|    auto exprs = Scripting::parseStatements(script);
  484|  5.42k|    if(exprs.empty())
  ------------------
  |  Branch (484:8): [True: 23, False: 5.40k]
  ------------------
  485|     23|    {
  486|     23|      return nonstd::make_unexpected("Empty Script");
  487|     23|    }
  488|  5.40k|    return {};
  489|  5.42k|  }
  490|  5.42k|  catch(RuntimeError& err)
  491|  5.42k|  {
  492|  1.28k|    return nonstd::make_unexpected(err.what());
  493|  1.28k|  }
  494|  5.42k|}
_ZN2BT9Scripting12ScriptParserC2ESt6vectorINS0_5TokenESaIS3_EE:
   28|  11.9k|  explicit ScriptParser(std::vector<Token> tokens) : tokens_(std::move(tokens))
   29|  11.9k|  {}
_ZN2BT9Scripting12ScriptParser8parseAllEv:
   32|  11.9k|  {
   33|  11.9k|    std::vector<Ast::expr_ptr> stmts;
   34|  4.77M|    while(!atEnd())
  ------------------
  |  Branch (34:11): [True: 4.76M, False: 11.9k]
  ------------------
   35|  4.76M|    {
   36|  4.76M|      stmts.push_back(parseExpr(0));
   37|       |      // consume optional semicolons between statements
   38|  4.77M|      while(check(TokenType::Semicolon))
  ------------------
  |  Branch (38:13): [True: 12.0k, False: 4.76M]
  ------------------
   39|  12.0k|      {
   40|  12.0k|        advance();
   41|  12.0k|      }
   42|  4.76M|    }
   43|  11.9k|    return stmts;
   44|  11.9k|  }
_ZNK2BT9Scripting12ScriptParser5atEndEv:
   73|  13.0M|  {
   74|  13.0M|    return peek().type == TokenType::EndOfInput;
   75|  13.0M|  }
_ZNK2BT9Scripting12ScriptParser4peekEv:
   60|  32.4M|  {
   61|  32.4M|    return tokens_[current_];
   62|  32.4M|  }
_ZN2BT9Scripting12ScriptParser9parseExprEi:
  256|  6.62M|  {
  257|  6.62M|    auto left = parsePrefix();
  258|       |
  259|  6.75M|    while(true)
  ------------------
  |  Branch (259:11): [True: 6.51M, Folded]
  ------------------
  260|  6.51M|    {
  261|  6.51M|      auto tokType = peek().type;
  262|  6.51M|      int lbp = leftBP(tokType);
  263|  6.51M|      if(lbp < 0 || lbp < minBP)
  ------------------
  |  Branch (263:10): [True: 4.82M, False: 1.69M]
  |  Branch (263:21): [True: 1.50M, False: 190k]
  ------------------
  264|  6.32M|      {
  265|  6.32M|        break;
  266|  6.32M|      }
  267|       |
  268|       |      // Assignment (non-associative: parse once, then break)
  269|   190k|      if(isAssignment(tokType))
  ------------------
  |  Branch (269:10): [True: 65.2k, False: 124k]
  ------------------
  270|  65.2k|      {
  271|  65.2k|        left = parseAssignment(std::move(left));
  272|  65.2k|        break;
  273|  65.2k|      }
  274|       |
  275|       |      // Ternary (non-associative: parse once, then break)
  276|   124k|      if(tokType == TokenType::Question)
  ------------------
  |  Branch (276:10): [True: 2.70k, False: 122k]
  ------------------
  277|  2.70k|      {
  278|  2.70k|        left = parseTernary(std::move(left));
  279|  2.70k|        break;
  280|  2.70k|      }
  281|       |
  282|       |      // Chained comparison
  283|   122k|      if(isComparison(tokType))
  ------------------
  |  Branch (283:10): [True: 35.2k, False: 87.0k]
  ------------------
  284|  35.2k|      {
  285|  35.2k|        left = parseChainedComparison(std::move(left));
  286|  35.2k|        continue;
  287|  35.2k|      }
  288|       |
  289|       |      // Regular left-associative binary operator
  290|  87.0k|      const auto& opTok = advance();
  291|       |      // Right BP = LBP + 1 for left-associativity
  292|  87.0k|      auto right = parseExpr(lbp + 1);
  293|  87.0k|      left = makeBinary(std::move(left), opTok.type, std::move(right));
  294|  87.0k|    }
  295|       |
  296|  6.62M|    return left;
  297|  6.62M|  }
_ZN2BT9Scripting12ScriptParser11parsePrefixEv:
  164|  6.62M|  {
  165|  6.62M|    const auto& tok = peek();
  166|       |
  167|       |    // Unary minus
  168|  6.62M|    if(tok.type == TokenType::Minus)
  ------------------
  |  Branch (168:8): [True: 25.7k, False: 6.60M]
  ------------------
  169|  25.7k|    {
  170|  25.7k|      advance();
  171|  25.7k|      auto operand = parseExpr(kPrefixBP);
  172|  25.7k|      return std::make_shared<Ast::ExprUnaryArithmetic>(Ast::ExprUnaryArithmetic::negate,
  173|  25.7k|                                                        std::move(operand));
  174|  25.7k|    }
  175|       |    // Bitwise complement
  176|  6.60M|    if(tok.type == TokenType::Tilde)
  ------------------
  |  Branch (176:8): [True: 87.0k, False: 6.51M]
  ------------------
  177|  87.0k|    {
  178|  87.0k|      advance();
  179|  87.0k|      auto operand = parseExpr(kPrefixBP);
  180|  87.0k|      return std::make_shared<Ast::ExprUnaryArithmetic>(
  181|  87.0k|          Ast::ExprUnaryArithmetic::complement, std::move(operand));
  182|  87.0k|    }
  183|       |    // Logical NOT
  184|  6.51M|    if(tok.type == TokenType::Bang)
  ------------------
  |  Branch (184:8): [True: 18.7k, False: 6.49M]
  ------------------
  185|  18.7k|    {
  186|  18.7k|      advance();
  187|  18.7k|      auto operand = parseExpr(kPrefixBP);
  188|  18.7k|      return std::make_shared<Ast::ExprUnaryArithmetic>(
  189|  18.7k|          Ast::ExprUnaryArithmetic::logical_not, std::move(operand));
  190|  18.7k|    }
  191|       |    // Parenthesized expression
  192|  6.49M|    if(tok.type == TokenType::LeftParen)
  ------------------
  |  Branch (192:8): [True: 112k, False: 6.38M]
  ------------------
  193|   112k|    {
  194|   112k|      advance();
  195|   112k|      auto expr = parseExpr(0);
  196|   112k|      expect(TokenType::RightParen, "expected ')'");
  197|   112k|      return expr;
  198|   112k|    }
  199|       |    // Boolean literal
  200|  6.38M|    if(tok.type == TokenType::Boolean)
  ------------------
  |  Branch (200:8): [True: 756, False: 6.38M]
  ------------------
  201|    756|    {
  202|    756|      advance();
  203|    756|      double val = (tok.text == "true") ? 1.0 : 0.0;
  ------------------
  |  Branch (203:20): [True: 538, False: 218]
  ------------------
  204|    756|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  205|    756|    }
  206|       |    // Integer literal
  207|  6.38M|    if(tok.type == TokenType::Integer)
  ------------------
  |  Branch (207:8): [True: 1.36M, False: 5.01M]
  ------------------
  208|  1.36M|    {
  209|  1.36M|      advance();
  210|  1.36M|      int64_t val = 0;
  211|  1.36M|      const char* first = tok.text.data();
  212|  1.36M|      const char* last = first + tok.text.size();
  213|  1.36M|      if(tok.text.size() > 2 && tok.text[0] == '0' &&
  ------------------
  |  Branch (213:10): [True: 17.0k, False: 1.35M]
  |  Branch (213:33): [True: 2.95k, False: 14.1k]
  ------------------
  214|  2.95k|         (tok.text[1] == 'x' || tok.text[1] == 'X'))
  ------------------
  |  Branch (214:11): [True: 315, False: 2.64k]
  |  Branch (214:33): [True: 1.37k, False: 1.26k]
  ------------------
  215|  1.69k|      {
  216|  1.69k|        std::from_chars(first + 2, last, val, 16);
  217|  1.69k|      }
  218|  1.36M|      else
  219|  1.36M|      {
  220|  1.36M|        std::from_chars(first, last, val, 10);
  221|  1.36M|      }
  222|  1.36M|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  223|  1.36M|    }
  224|       |    // Real literal
  225|  5.01M|    if(tok.type == TokenType::Real)
  ------------------
  |  Branch (225:8): [True: 4.96k, False: 5.00M]
  ------------------
  226|  4.96k|    {
  227|  4.96k|      advance();
  228|  4.96k|      double val = convertFromString<double>(tok.text);
  229|  4.96k|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  230|  4.96k|    }
  231|       |    // String literal
  232|  5.00M|    if(tok.type == TokenType::String)
  ------------------
  |  Branch (232:8): [True: 79.6k, False: 4.93M]
  ------------------
  233|  79.6k|    {
  234|  79.6k|      advance();
  235|  79.6k|      return std::make_shared<Ast::ExprLiteral>(Any(std::string(tok.text)));
  236|  79.6k|    }
  237|       |    // Identifier
  238|  4.93M|    if(tok.type == TokenType::Identifier)
  ------------------
  |  Branch (238:8): [True: 4.92M, False: 3.51k]
  ------------------
  239|  4.92M|    {
  240|  4.92M|      advance();
  241|  4.92M|      return std::make_shared<Ast::ExprName>(std::string(tok.text));
  242|  4.92M|    }
  243|       |    // Error token from tokenizer
  244|  3.51k|    if(tok.type == TokenType::Error)
  ------------------
  |  Branch (244:8): [True: 1.76k, False: 1.74k]
  ------------------
  245|  1.76k|    {
  246|  1.76k|      throw RuntimeError(
  247|  1.76k|          StrCat("Invalid token '", tok.text, "' at position ", std::to_string(tok.pos)));
  248|  1.76k|    }
  249|       |
  250|  1.74k|    throw RuntimeError(StrCat("Expected operand at position ", std::to_string(tok.pos),
  251|  1.74k|                              " (got '", tok.text, "')"));
  252|  3.51k|  }
_ZN2BT9Scripting12ScriptParser6expectENS0_9TokenTypeEPKc:
   83|  4.73k|  {
   84|  4.73k|    if(!check(type))
  ------------------
  |  Branch (84:8): [True: 354, False: 4.37k]
  ------------------
   85|    354|    {
   86|    354|      throw RuntimeError(StrCat("Parse error at position ", std::to_string(peek().pos),
   87|    354|                                ": ", msg, " (got '", peek().text, "')"));
   88|    354|    }
   89|  4.37k|    return advance();
   90|  4.73k|  }
_ZN2BT9Scripting12ScriptParser6leftBPENS0_9TokenTypeE:
   97|  6.51M|  {
   98|  6.51M|    switch(type)
   99|  6.51M|    {
  100|       |      // Assignment (level 1, non-associative)
  101|  30.3k|      case TokenType::ColonEqual:
  ------------------
  |  Branch (101:7): [True: 30.3k, False: 6.48M]
  ------------------
  102|  47.5k|      case TokenType::Equal:
  ------------------
  |  Branch (102:7): [True: 17.1k, False: 6.50M]
  ------------------
  103|  61.9k|      case TokenType::PlusEqual:
  ------------------
  |  Branch (103:7): [True: 14.4k, False: 6.50M]
  ------------------
  104|  63.1k|      case TokenType::MinusEqual:
  ------------------
  |  Branch (104:7): [True: 1.19k, False: 6.51M]
  ------------------
  105|  64.1k|      case TokenType::StarEqual:
  ------------------
  |  Branch (105:7): [True: 1.04k, False: 6.51M]
  ------------------
  106|  65.6k|      case TokenType::SlashEqual:
  ------------------
  |  Branch (106:7): [True: 1.49k, False: 6.51M]
  ------------------
  107|  65.6k|        return kAssignmentBP;
  108|       |      // Ternary (level 2, non-associative)
  109|  3.74k|      case TokenType::Question:
  ------------------
  |  Branch (109:7): [True: 3.74k, False: 6.51M]
  ------------------
  110|  3.74k|        return kTernaryBP;
  111|       |      // Logical OR (level 3)
  112|  2.50k|      case TokenType::PipePipe:
  ------------------
  |  Branch (112:7): [True: 2.50k, False: 6.51M]
  ------------------
  113|  2.50k|        return 6;
  114|       |      // Logical AND (level 4)
  115|  2.45k|      case TokenType::AmpAmp:
  ------------------
  |  Branch (115:7): [True: 2.45k, False: 6.51M]
  ------------------
  116|  2.45k|        return 8;
  117|       |      // Comparison (level 5, chainable)
  118|  12.7k|      case TokenType::EqualEqual:
  ------------------
  |  Branch (118:7): [True: 12.7k, False: 6.50M]
  ------------------
  119|   137k|      case TokenType::BangEqual:
  ------------------
  |  Branch (119:7): [True: 124k, False: 6.39M]
  ------------------
  120|   300k|      case TokenType::Less:
  ------------------
  |  Branch (120:7): [True: 162k, False: 6.35M]
  ------------------
  121|  1.44M|      case TokenType::Greater:
  ------------------
  |  Branch (121:7): [True: 1.14M, False: 5.37M]
  ------------------
  122|  1.45M|      case TokenType::LessEqual:
  ------------------
  |  Branch (122:7): [True: 13.5k, False: 6.50M]
  ------------------
  123|  1.46M|      case TokenType::GreaterEqual:
  ------------------
  |  Branch (123:7): [True: 8.91k, False: 6.50M]
  ------------------
  124|  1.46M|        return kComparisonBP;
  125|       |      // Bitwise OR/XOR (level 6)
  126|   100k|      case TokenType::Pipe:
  ------------------
  |  Branch (126:7): [True: 100k, False: 6.41M]
  ------------------
  127|   101k|      case TokenType::Caret:
  ------------------
  |  Branch (127:7): [True: 1.12k, False: 6.51M]
  ------------------
  128|   101k|        return 12;
  129|       |      // Bitwise AND (level 7)
  130|  5.15k|      case TokenType::Ampersand:
  ------------------
  |  Branch (130:7): [True: 5.15k, False: 6.51M]
  ------------------
  131|  5.15k|        return 14;
  132|       |      // Add/Sub/Concat (level 8)
  133|  23.6k|      case TokenType::Plus:
  ------------------
  |  Branch (133:7): [True: 23.6k, False: 6.49M]
  ------------------
  134|  28.7k|      case TokenType::Minus:
  ------------------
  |  Branch (134:7): [True: 5.06k, False: 6.51M]
  ------------------
  135|  48.3k|      case TokenType::DotDot:
  ------------------
  |  Branch (135:7): [True: 19.6k, False: 6.49M]
  ------------------
  136|  48.3k|        return 16;
  137|       |      // Mul/Div (level 9)
  138|  1.28k|      case TokenType::Star:
  ------------------
  |  Branch (138:7): [True: 1.28k, False: 6.51M]
  ------------------
  139|  2.89k|      case TokenType::Slash:
  ------------------
  |  Branch (139:7): [True: 1.60k, False: 6.51M]
  ------------------
  140|  2.89k|        return kMulDivBP;
  141|  4.82M|      default:
  ------------------
  |  Branch (141:7): [True: 4.82M, False: 1.69M]
  ------------------
  142|  4.82M|        return -1;
  143|  6.51M|    }
  144|  6.51M|  }
_ZN2BT9Scripting12ScriptParser12isAssignmentENS0_9TokenTypeE:
  154|   190k|  {
  155|   190k|    return type == TokenType::ColonEqual || type == TokenType::Equal ||
  ------------------
  |  Branch (155:12): [True: 30.1k, False: 160k]
  |  Branch (155:45): [True: 16.9k, False: 143k]
  ------------------
  156|   143k|           type == TokenType::PlusEqual || type == TokenType::MinusEqual ||
  ------------------
  |  Branch (156:12): [True: 14.4k, False: 128k]
  |  Branch (156:44): [True: 1.18k, False: 127k]
  ------------------
  157|   127k|           type == TokenType::StarEqual || type == TokenType::SlashEqual;
  ------------------
  |  Branch (157:12): [True: 1.04k, False: 126k]
  |  Branch (157:44): [True: 1.49k, False: 124k]
  ------------------
  158|   190k|  }
_ZN2BT9Scripting12ScriptParser15parseAssignmentESt10shared_ptrINS_3Ast8ExprBaseEE:
  300|  65.2k|  {
  301|  65.2k|    const auto& opTok = advance();
  302|  65.2k|    Ast::ExprAssignment::op_t op{};
  303|  65.2k|    switch(opTok.type)
  304|  65.2k|    {
  305|  30.1k|      case TokenType::ColonEqual:
  ------------------
  |  Branch (305:7): [True: 30.1k, False: 35.1k]
  ------------------
  306|  30.1k|        op = Ast::ExprAssignment::assign_create;
  307|  30.1k|        break;
  308|  16.9k|      case TokenType::Equal:
  ------------------
  |  Branch (308:7): [True: 16.9k, False: 48.3k]
  ------------------
  309|  16.9k|        op = Ast::ExprAssignment::assign_existing;
  310|  16.9k|        break;
  311|  14.4k|      case TokenType::PlusEqual:
  ------------------
  |  Branch (311:7): [True: 14.4k, False: 50.8k]
  ------------------
  312|  14.4k|        op = Ast::ExprAssignment::assign_plus;
  313|  14.4k|        break;
  314|  1.18k|      case TokenType::MinusEqual:
  ------------------
  |  Branch (314:7): [True: 1.18k, False: 64.0k]
  ------------------
  315|  1.18k|        op = Ast::ExprAssignment::assign_minus;
  316|  1.18k|        break;
  317|  1.04k|      case TokenType::StarEqual:
  ------------------
  |  Branch (317:7): [True: 1.04k, False: 64.2k]
  ------------------
  318|  1.04k|        op = Ast::ExprAssignment::assign_times;
  319|  1.04k|        break;
  320|  1.49k|      case TokenType::SlashEqual:
  ------------------
  |  Branch (320:7): [True: 1.49k, False: 63.7k]
  ------------------
  321|  1.49k|        op = Ast::ExprAssignment::assign_div;
  322|  1.49k|        break;
  323|      0|      default:
  ------------------
  |  Branch (323:7): [True: 0, False: 65.2k]
  ------------------
  324|      0|        throw RuntimeError("Internal error: unexpected assignment op");
  325|  65.2k|    }
  326|       |    // Parse RHS -- use minBP=0 to allow full expression
  327|  65.2k|    auto right = parseExpr(0);
  328|  65.2k|    return std::make_shared<Ast::ExprAssignment>(std::move(left), op, std::move(right));
  329|  65.2k|  }
_ZN2BT9Scripting12ScriptParser12parseTernaryESt10shared_ptrINS_3Ast8ExprBaseEE:
  332|  2.70k|  {
  333|  2.70k|    advance();                     // consume '?'
  334|  2.70k|    auto thenExpr = parseExpr(0);  // full expression inside
  335|  2.70k|    expect(TokenType::Colon, "expected ':' in ternary expression");
  336|  2.70k|    auto elseExpr = parseExpr(kTernaryBP);
  337|  2.70k|    return std::make_shared<Ast::ExprIf>(std::move(condition), std::move(thenExpr),
  338|  2.70k|                                         std::move(elseExpr));
  339|  2.70k|  }
_ZN2BT9Scripting12ScriptParser12isComparisonENS0_9TokenTypeE:
  147|  1.61M|  {
  148|  1.61M|    return type == TokenType::EqualEqual || type == TokenType::BangEqual ||
  ------------------
  |  Branch (148:12): [True: 16.4k, False: 1.60M]
  |  Branch (148:45): [True: 128k, False: 1.47M]
  ------------------
  149|  1.47M|           type == TokenType::Less || type == TokenType::Greater ||
  ------------------
  |  Branch (149:12): [True: 169k, False: 1.30M]
  |  Branch (149:39): [True: 1.15M, False: 152k]
  ------------------
  150|   152k|           type == TokenType::LessEqual || type == TokenType::GreaterEqual;
  ------------------
  |  Branch (150:12): [True: 17.1k, False: 135k]
  |  Branch (150:44): [True: 14.9k, False: 120k]
  ------------------
  151|  1.61M|  }
_ZN2BT9Scripting12ScriptParser22parseChainedComparisonESt10shared_ptrINS_3Ast8ExprBaseEE:
  342|  35.2k|  {
  343|  35.2k|    auto node = std::make_shared<Ast::ExprComparison>();
  344|  35.2k|    node->operands.push_back(std::move(first));
  345|       |
  346|  1.49M|    while(isComparison(peek().type))
  ------------------
  |  Branch (346:11): [True: 1.46M, False: 35.2k]
  ------------------
  347|  1.46M|    {
  348|  1.46M|      node->ops.push_back(mapComparisonOp(advance().type));
  349|       |      // Parse the next operand above comparison level
  350|       |      // so that arithmetic binds tighter
  351|  1.46M|      node->operands.push_back(parseExpr(kComparisonBP + 1));
  352|  1.46M|    }
  353|  35.2k|    return node;
  354|  35.2k|  }
_ZN2BT9Scripting12ScriptParser15mapComparisonOpENS0_9TokenTypeE:
  357|  1.46M|  {
  358|  1.46M|    switch(type)
  359|  1.46M|    {
  360|  12.5k|      case TokenType::EqualEqual:
  ------------------
  |  Branch (360:7): [True: 12.5k, False: 1.44M]
  ------------------
  361|  12.5k|        return Ast::ExprComparison::equal;
  362|   124k|      case TokenType::BangEqual:
  ------------------
  |  Branch (362:7): [True: 124k, False: 1.33M]
  ------------------
  363|   124k|        return Ast::ExprComparison::not_equal;
  364|   160k|      case TokenType::Less:
  ------------------
  |  Branch (364:7): [True: 160k, False: 1.30M]
  ------------------
  365|   160k|        return Ast::ExprComparison::less;
  366|  1.14M|      case TokenType::Greater:
  ------------------
  |  Branch (366:7): [True: 1.14M, False: 318k]
  ------------------
  367|  1.14M|        return Ast::ExprComparison::greater;
  368|  12.4k|      case TokenType::LessEqual:
  ------------------
  |  Branch (368:7): [True: 12.4k, False: 1.44M]
  ------------------
  369|  12.4k|        return Ast::ExprComparison::less_equal;
  370|  8.42k|      case TokenType::GreaterEqual:
  ------------------
  |  Branch (370:7): [True: 8.42k, False: 1.45M]
  ------------------
  371|  8.42k|        return Ast::ExprComparison::greater_equal;
  372|      0|      default:
  ------------------
  |  Branch (372:7): [True: 0, False: 1.46M]
  ------------------
  373|      0|        throw RuntimeError("Internal error: not a comparison op");
  374|  1.46M|    }
  375|  1.46M|  }
_ZN2BT9Scripting12ScriptParser10makeBinaryESt10shared_ptrINS_3Ast8ExprBaseEENS0_9TokenTypeES5_:
  379|  86.6k|  {
  380|  86.6k|    Ast::ExprBinaryArithmetic::op_t op{};
  381|  86.6k|    switch(opType)
  382|  86.6k|    {
  383|  14.4k|      case TokenType::Plus:
  ------------------
  |  Branch (383:7): [True: 14.4k, False: 72.1k]
  ------------------
  384|  14.4k|        op = Ast::ExprBinaryArithmetic::plus;
  385|  14.4k|        break;
  386|  2.50k|      case TokenType::Minus:
  ------------------
  |  Branch (386:7): [True: 2.50k, False: 84.1k]
  ------------------
  387|  2.50k|        op = Ast::ExprBinaryArithmetic::minus;
  388|  2.50k|        break;
  389|    718|      case TokenType::Star:
  ------------------
  |  Branch (389:7): [True: 718, False: 85.8k]
  ------------------
  390|    718|        op = Ast::ExprBinaryArithmetic::times;
  391|    718|        break;
  392|    935|      case TokenType::Slash:
  ------------------
  |  Branch (392:7): [True: 935, False: 85.6k]
  ------------------
  393|    935|        op = Ast::ExprBinaryArithmetic::div;
  394|    935|        break;
  395|  12.3k|      case TokenType::DotDot:
  ------------------
  |  Branch (395:7): [True: 12.3k, False: 74.3k]
  ------------------
  396|  12.3k|        op = Ast::ExprBinaryArithmetic::concat;
  397|  12.3k|        break;
  398|  2.12k|      case TokenType::Ampersand:
  ------------------
  |  Branch (398:7): [True: 2.12k, False: 84.4k]
  ------------------
  399|  2.12k|        op = Ast::ExprBinaryArithmetic::bit_and;
  400|  2.12k|        break;
  401|  50.2k|      case TokenType::Pipe:
  ------------------
  |  Branch (401:7): [True: 50.2k, False: 36.3k]
  ------------------
  402|  50.2k|        op = Ast::ExprBinaryArithmetic::bit_or;
  403|  50.2k|        break;
  404|    574|      case TokenType::Caret:
  ------------------
  |  Branch (404:7): [True: 574, False: 86.0k]
  ------------------
  405|    574|        op = Ast::ExprBinaryArithmetic::bit_xor;
  406|    574|        break;
  407|  1.46k|      case TokenType::AmpAmp:
  ------------------
  |  Branch (407:7): [True: 1.46k, False: 85.1k]
  ------------------
  408|  1.46k|        op = Ast::ExprBinaryArithmetic::logic_and;
  409|  1.46k|        break;
  410|  1.25k|      case TokenType::PipePipe:
  ------------------
  |  Branch (410:7): [True: 1.25k, False: 85.3k]
  ------------------
  411|  1.25k|        op = Ast::ExprBinaryArithmetic::logic_or;
  412|  1.25k|        break;
  413|      0|      default:
  ------------------
  |  Branch (413:7): [True: 0, False: 86.6k]
  ------------------
  414|      0|        throw RuntimeError("Internal error: unknown binary operator");
  415|  86.6k|    }
  416|  86.6k|    return std::make_shared<Ast::ExprBinaryArithmetic>(std::move(left), op,
  417|  86.6k|                                                       std::move(right));
  418|  86.6k|  }
_ZNK2BT9Scripting12ScriptParser5checkENS0_9TokenTypeE:
   78|  4.77M|  {
   79|  4.77M|    return peek().type == type;
   80|  4.77M|  }
_ZN2BT9Scripting12ScriptParser7advanceEv:
   65|  8.25M|  {
   66|  8.25M|    const Token& tok = tokens_[current_];
   67|  8.25M|    if(!atEnd())
  ------------------
  |  Branch (67:8): [True: 8.25M, False: 0]
  ------------------
   68|  8.25M|      current_++;
   69|  8.25M|    return tok;
   70|  8.25M|  }
script_parser.cpp:_ZZN2BT11ParseScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENK3$_0clERNS_3Ast11EnvironmentE:
  441|  3.94k|    return [exprs = std::move(exprs), script](Ast::Environment& env) {
  442|  3.94k|      try
  443|  3.94k|      {
  444|   182k|        for(size_t i = 0; i < exprs.size() - 1; ++i)
  ------------------
  |  Branch (444:27): [True: 178k, False: 3.94k]
  ------------------
  445|   178k|        {
  446|   178k|          exprs[i]->evaluate(env);
  447|   178k|        }
  448|  3.94k|        return exprs.back()->evaluate(env);
  449|  3.94k|      }
  450|  3.94k|      catch(RuntimeError& err)
  451|  3.94k|      {
  452|    943|        throw RuntimeError(StrCat("Error in script [", script, "]\n", err.what()));
  453|    943|      }
  454|  3.94k|    };

_ZN2BT9Scripting8tokenizeERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  224|  11.9k|{
  225|  11.9k|  std::vector<Token> tokens;
  226|  11.9k|  const size_t len = source.size();
  227|  11.9k|  size_t i = 0;
  228|       |
  229|  38.0M|  while(i < len)
  ------------------
  |  Branch (229:9): [True: 38.0M, False: 11.9k]
  ------------------
  230|  38.0M|  {
  231|  38.0M|    const char c = source[i];
  232|       |
  233|       |    // Skip whitespace (space, tab, newline, carriage return)
  234|  38.0M|    if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
  ------------------
  |  Branch (234:8): [True: 3.60k, False: 38.0M]
  |  Branch (234:20): [True: 10.8k, False: 38.0M]
  |  Branch (234:33): [True: 270k, False: 37.7M]
  |  Branch (234:46): [True: 2.16k, False: 37.7M]
  ------------------
  235|   286k|    {
  236|   286k|      ++i;
  237|   286k|      continue;
  238|   286k|    }
  239|       |
  240|  37.7M|    const size_t start = i;
  241|       |
  242|       |    // Single-quoted string literal
  243|  37.7M|    if(c == '\'')
  ------------------
  |  Branch (243:8): [True: 314k, False: 37.4M]
  ------------------
  244|   314k|    {
  245|   314k|      ++i;
  246|  70.3M|      while(i < len && source[i] != '\'')
  ------------------
  |  Branch (246:13): [True: 70.3M, False: 351]
  |  Branch (246:24): [True: 70.0M, False: 313k]
  ------------------
  247|  70.0M|      {
  248|  70.0M|        ++i;
  249|  70.0M|      }
  250|   314k|      if(i < len)
  ------------------
  |  Branch (250:10): [True: 313k, False: 351]
  ------------------
  251|   313k|      {
  252|       |        // extract content without quotes
  253|   313k|        std::string_view text(&source[start + 1], i - start - 1);
  254|   313k|        tokens.push_back({ TokenType::String, text, start });
  255|   313k|        ++i;  // skip closing quote
  256|   313k|      }
  257|    351|      else
  258|    351|      {
  259|    351|        std::string_view text(&source[start], i - start);
  260|    351|        tokens.push_back({ TokenType::Error, text, start });
  261|    351|      }
  262|   314k|      continue;
  263|   314k|    }
  264|       |
  265|       |    // Number literal (integer or real)
  266|  37.4M|    if(isDigit(c))
  ------------------
  |  Branch (266:8): [True: 4.03M, False: 33.3M]
  ------------------
  267|  4.03M|    {
  268|  4.03M|      NumberResult nr;
  269|  4.03M|      const bool is_hex =
  270|  4.03M|          c == '0' && i + 1 < len && (source[i + 1] == 'x' || source[i + 1] == 'X');
  ------------------
  |  Branch (270:11): [True: 515k, False: 3.51M]
  |  Branch (270:23): [True: 515k, False: 664]
  |  Branch (270:39): [True: 259k, False: 255k]
  |  Branch (270:63): [True: 4.95k, False: 250k]
  ------------------
  271|  4.03M|      if(is_hex)
  ------------------
  |  Branch (271:10): [True: 264k, False: 3.76M]
  ------------------
  272|   264k|      {
  273|   264k|        nr = scanHexNumber(source, len, i);
  274|   264k|      }
  275|  3.76M|      else
  276|  3.76M|      {
  277|  3.76M|        nr = scanDecimalNumber(source, len, i);
  278|  3.76M|      }
  279|       |
  280|  4.03M|      std::string_view text(&source[start], i - start);
  281|  4.03M|      if(nr.has_error)
  ------------------
  |  Branch (281:10): [True: 555k, False: 3.47M]
  ------------------
  282|   555k|      {
  283|   555k|        tokens.push_back({ TokenType::Error, text, start });
  284|   555k|      }
  285|  3.47M|      else if(nr.is_real)
  ------------------
  |  Branch (285:15): [True: 49.4k, False: 3.42M]
  ------------------
  286|  49.4k|      {
  287|  49.4k|        tokens.push_back({ TokenType::Real, text, start });
  288|  49.4k|      }
  289|  3.42M|      else
  290|  3.42M|      {
  291|  3.42M|        tokens.push_back({ TokenType::Integer, text, start });
  292|  3.42M|      }
  293|  4.03M|      continue;
  294|  4.03M|    }
  295|       |
  296|       |    // Identifier or keyword (true/false)
  297|  33.3M|    if(isIdentStart(c))
  ------------------
  |  Branch (297:8): [True: 6.66M, False: 26.7M]
  ------------------
  298|  6.66M|    {
  299|  6.66M|      ++i;  // consume start character (may not be isIdentChar, e.g. '@')
  300|  52.0M|      while(i < len && isIdentChar(source[i]))
  ------------------
  |  Branch (300:13): [True: 51.9M, False: 2.73k]
  |  Branch (300:24): [True: 45.3M, False: 6.66M]
  ------------------
  301|  45.3M|      {
  302|  45.3M|        ++i;
  303|  45.3M|      }
  304|  6.66M|      if(std::string_view text(&source[start], i - start); text == "true" || text == "fal"
  ------------------
  |  Branch (304:60): [True: 8.76k, False: 6.66M]
  |  Branch (304:78): [True: 725, False: 6.66M]
  ------------------
  305|  6.66M|                                                                                     "se")
  306|  9.49k|      {
  307|  9.49k|        tokens.push_back({ TokenType::Boolean, text, start });
  308|  9.49k|      }
  309|  6.66M|      else
  310|  6.66M|      {
  311|  6.66M|        tokens.push_back({ TokenType::Identifier, text, start });
  312|  6.66M|      }
  313|  6.66M|      continue;
  314|  6.66M|    }
  315|       |
  316|       |    // Two-character operators (check before single-char)
  317|  26.7M|    if(i + 1 < len)
  ------------------
  |  Branch (317:8): [True: 26.7M, False: 2.13k]
  ------------------
  318|  26.7M|    {
  319|  26.7M|      TokenType two_char_type = matchTwoCharOp(c, source[i + 1]);
  320|  26.7M|      if(two_char_type != TokenType::Error)
  ------------------
  |  Branch (320:10): [True: 355k, False: 26.3M]
  ------------------
  321|   355k|      {
  322|   355k|        std::string_view text(&source[start], 2);
  323|   355k|        tokens.push_back({ two_char_type, text, start });
  324|   355k|        i += 2;
  325|   355k|        continue;
  326|   355k|      }
  327|  26.7M|    }
  328|       |
  329|       |    // Single-character operators and delimiters
  330|  26.3M|    std::string_view text(&source[start], 1);
  331|  26.3M|    tokens.push_back({ matchSingleCharOp(c), text, start });
  332|  26.3M|    ++i;
  333|  26.3M|  }
  334|       |
  335|       |  // Sentinel
  336|  11.9k|  tokens.push_back({ TokenType::EndOfInput, {}, i });
  337|  11.9k|  return tokens;
  338|  11.9k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_17isDigitEc:
   34|  67.0M|{
   35|  67.0M|  return std::isdigit(static_cast<unsigned char>(c)) != 0;
   36|  67.0M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_113scanHexNumberERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   59|   264k|{
   60|   264k|  NumberResult result;
   61|   264k|  i += 2;  // skip "0x"/"0X"
   62|   264k|  if(i >= len || !isHexDigit(source[i]))
  ------------------
  |  Branch (62:6): [True: 41, False: 264k]
  |  Branch (62:18): [True: 259k, False: 4.73k]
  ------------------
   63|   259k|  {
   64|   259k|    result.has_error = true;
   65|   259k|  }
   66|  4.73k|  else
   67|  4.73k|  {
   68|   140k|    while(i < len && isHexDigit(source[i]))
  ------------------
  |  Branch (68:11): [True: 139k, False: 491]
  |  Branch (68:22): [True: 135k, False: 4.24k]
  ------------------
   69|   135k|    {
   70|   135k|      ++i;
   71|   135k|    }
   72|  4.73k|  }
   73|       |  // Hex numbers don't support dot or exponent
   74|   264k|  if(i < len && (source[i] == '.' || isIdentChar(source[i])))
  ------------------
  |  Branch (74:6): [True: 263k, False: 532]
  |  Branch (74:18): [True: 290, False: 263k]
  |  Branch (74:38): [True: 245k, False: 17.7k]
  ------------------
   75|   246k|  {
   76|   246k|    result.has_error = true;
   77|   246k|    consumeTrailingGarbage(source, len, i);
   78|   246k|  }
   79|   264k|  return result;
   80|   264k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_110isHexDigitEc:
   39|   404k|{
   40|   404k|  return std::isxdigit(static_cast<unsigned char>(c)) != 0;
   41|   404k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_122consumeTrailingGarbageERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   45|   248k|{
   46|   533k|  while(i < len && (isIdentChar(source[i]) || source[i] == '.'))
  ------------------
  |  Branch (46:9): [True: 533k, False: 165]
  |  Branch (46:21): [True: 284k, False: 248k]
  |  Branch (46:47): [True: 677, False: 248k]
  ------------------
   47|   284k|  {
   48|   284k|    ++i;
   49|   284k|  }
   50|   248k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_117scanDecimalNumberERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   83|  3.76M|{
   84|  3.76M|  NumberResult result;
   85|       |
   86|       |  // Integer part
   87|  19.6M|  while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (87:9): [True: 19.6M, False: 2.43k]
  |  Branch (87:20): [True: 15.8M, False: 3.76M]
  ------------------
   88|  15.8M|  {
   89|  15.8M|    ++i;
   90|  15.8M|  }
   91|       |  // Fractional part
   92|  3.76M|  if(i < len && source[i] == '.')
  ------------------
  |  Branch (92:6): [True: 3.76M, False: 2.43k]
  |  Branch (92:17): [True: 26.2k, False: 3.73M]
  ------------------
   93|  26.2k|  {
   94|       |    // Distinguish from ".." (concat operator)
   95|  26.2k|    if(i + 1 < len && source[i + 1] == '.')
  ------------------
  |  Branch (95:8): [True: 26.2k, False: 10]
  |  Branch (95:23): [True: 13.0k, False: 13.2k]
  ------------------
   96|  13.0k|    {
   97|       |      // Stop here: "65.." is Integer("65") + DotDot
   98|  13.0k|    }
   99|  13.2k|    else if(i + 1 < len && isDigit(source[i + 1]))
  ------------------
  |  Branch (99:13): [True: 13.2k, False: 10]
  |  Branch (99:28): [True: 10.9k, False: 2.31k]
  ------------------
  100|  10.9k|    {
  101|  10.9k|      result.is_real = true;
  102|  10.9k|      ++i;  // consume '.'
  103|  9.65M|      while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (103:13): [True: 9.65M, False: 112]
  |  Branch (103:24): [True: 9.64M, False: 10.7k]
  ------------------
  104|  9.64M|      {
  105|  9.64M|        ++i;
  106|  9.64M|      }
  107|  10.9k|    }
  108|  2.32k|    else
  109|  2.32k|    {
  110|       |      // "65." or "65.x" -- incomplete real
  111|  2.32k|      result.has_error = true;
  112|  2.32k|      ++i;  // consume the dot
  113|  2.32k|      consumeTrailingGarbage(source, len, i);
  114|  2.32k|    }
  115|  26.2k|  }
  116|       |  // Exponent (only for decimal numbers)
  117|  3.76M|  if(!result.has_error && i < len && (source[i] == 'e' || source[i] == 'E'))
  ------------------
  |  Branch (117:6): [True: 3.76M, False: 2.32k]
  |  Branch (117:27): [True: 3.76M, False: 2.54k]
  |  Branch (117:39): [True: 6.12k, False: 3.75M]
  |  Branch (117:59): [True: 46.6k, False: 3.70M]
  ------------------
  118|  52.8k|  {
  119|  52.8k|    result.is_real = true;
  120|  52.8k|    ++i;  // consume 'e'/'E'
  121|  52.8k|    if(i < len && (source[i] == '+' || source[i] == '-'))
  ------------------
  |  Branch (121:8): [True: 52.7k, False: 44]
  |  Branch (121:20): [True: 374, False: 52.3k]
  |  Branch (121:40): [True: 11.8k, False: 40.5k]
  ------------------
  122|  12.2k|    {
  123|  12.2k|      ++i;  // consume sign
  124|  12.2k|    }
  125|  52.8k|    if(i >= len || !isDigit(source[i]))
  ------------------
  |  Branch (125:8): [True: 77, False: 52.7k]
  |  Branch (125:20): [True: 5.86k, False: 46.8k]
  ------------------
  126|  5.94k|    {
  127|  5.94k|      result.has_error = true;
  128|  5.94k|    }
  129|  46.8k|    else
  130|  46.8k|    {
  131|   262k|      while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (131:13): [True: 262k, False: 319]
  |  Branch (131:24): [True: 215k, False: 46.5k]
  ------------------
  132|   215k|      {
  133|   215k|        ++i;
  134|   215k|      }
  135|  46.8k|    }
  136|  52.8k|  }
  137|       |  // Trailing alpha (e.g. "3foo", "65.43foo")
  138|  3.76M|  if(!result.has_error && i < len && isIdentStart(source[i]))
  ------------------
  |  Branch (138:6): [True: 3.75M, False: 8.27k]
  |  Branch (138:27): [True: 3.75M, False: 2.86k]
  |  Branch (138:38): [True: 286k, False: 3.46M]
  ------------------
  139|   286k|  {
  140|   286k|    result.has_error = true;
  141|  1.73M|    while(i < len && isIdentChar(source[i]))
  ------------------
  |  Branch (141:11): [True: 1.73M, False: 92]
  |  Branch (141:22): [True: 1.44M, False: 286k]
  ------------------
  142|  1.44M|    {
  143|  1.44M|      ++i;
  144|  1.44M|    }
  145|   286k|  }
  146|  3.76M|  return result;
  147|  3.76M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_112isIdentStartEc:
   24|  37.1M|{
   25|  37.1M|  return std::isalpha(static_cast<unsigned char>(c)) != 0 || c == '_' || c == '@';
  ------------------
  |  Branch (25:10): [True: 1.35M, False: 35.7M]
  |  Branch (25:62): [True: 1.13k, False: 35.7M]
  |  Branch (25:74): [True: 5.60M, False: 30.1M]
  ------------------
   26|  37.1M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_111isIdentCharEc:
   29|  54.5M|{
   30|  54.5M|  return std::isalnum(static_cast<unsigned char>(c)) != 0 || c == '_';
  ------------------
  |  Branch (30:10): [True: 47.3M, False: 7.22M]
  |  Branch (30:62): [True: 6.58k, False: 7.22M]
  ------------------
   31|  54.5M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_114matchTwoCharOpEcc:
  150|  26.7M|{
  151|  26.7M|  if(c == '.' && next == '.')
  ------------------
  |  Branch (151:6): [True: 99.7k, False: 26.6M]
  |  Branch (151:18): [True: 62.5k, False: 37.1k]
  ------------------
  152|  62.5k|    return TokenType::DotDot;
  153|  26.6M|  if(c == '&' && next == '&')
  ------------------
  |  Branch (153:6): [True: 17.0k, False: 26.6M]
  |  Branch (153:18): [True: 13.7k, False: 3.32k]
  ------------------
  154|  13.7k|    return TokenType::AmpAmp;
  155|  26.6M|  if(c == '|' && next == '|')
  ------------------
  |  Branch (155:6): [True: 55.6k, False: 26.5M]
  |  Branch (155:18): [True: 3.58k, False: 52.1k]
  ------------------
  156|  3.58k|    return TokenType::PipePipe;
  157|  26.6M|  if(c == '=' && next == '=')
  ------------------
  |  Branch (157:6): [True: 80.1k, False: 26.5M]
  |  Branch (157:18): [True: 16.8k, False: 63.2k]
  ------------------
  158|  16.8k|    return TokenType::EqualEqual;
  159|  26.6M|  if(c == '!' && next == '=')
  ------------------
  |  Branch (159:6): [True: 214k, False: 26.4M]
  |  Branch (159:18): [True: 146k, False: 67.9k]
  ------------------
  160|   146k|    return TokenType::BangEqual;
  161|  26.4M|  if(c == '<' && next == '=')
  ------------------
  |  Branch (161:6): [True: 205k, False: 26.2M]
  |  Branch (161:18): [True: 29.9k, False: 175k]
  ------------------
  162|  29.9k|    return TokenType::LessEqual;
  163|  26.4M|  if(c == '>' && next == '=')
  ------------------
  |  Branch (163:6): [True: 1.60M, False: 24.8M]
  |  Branch (163:18): [True: 10.0k, False: 1.59M]
  ------------------
  164|  10.0k|    return TokenType::GreaterEqual;
  165|  26.4M|  if(c == ':' && next == '=')
  ------------------
  |  Branch (165:6): [True: 69.1k, False: 26.3M]
  |  Branch (165:18): [True: 50.9k, False: 18.2k]
  ------------------
  166|  50.9k|    return TokenType::ColonEqual;
  167|  26.3M|  if(c == '+' && next == '=')
  ------------------
  |  Branch (167:6): [True: 37.6k, False: 26.3M]
  |  Branch (167:18): [True: 15.5k, False: 22.0k]
  ------------------
  168|  15.5k|    return TokenType::PlusEqual;
  169|  26.3M|  if(c == '-' && next == '=')
  ------------------
  |  Branch (169:6): [True: 105k, False: 26.2M]
  |  Branch (169:18): [True: 2.34k, False: 103k]
  ------------------
  170|  2.34k|    return TokenType::MinusEqual;
  171|  26.3M|  if(c == '*' && next == '=')
  ------------------
  |  Branch (171:6): [True: 3.30k, False: 26.3M]
  |  Branch (171:18): [True: 1.40k, False: 1.89k]
  ------------------
  172|  1.40k|    return TokenType::StarEqual;
  173|  26.3M|  if(c == '/' && next == '=')
  ------------------
  |  Branch (173:6): [True: 9.66k, False: 26.3M]
  |  Branch (173:18): [True: 2.47k, False: 7.18k]
  ------------------
  174|  2.47k|    return TokenType::SlashEqual;
  175|  26.3M|  return TokenType::Error;
  176|  26.3M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_117matchSingleCharOpEc:
  179|  26.3M|{
  180|  26.3M|  switch(c)
  181|  26.3M|  {
  182|  22.1k|    case '+':
  ------------------
  |  Branch (182:5): [True: 22.1k, False: 26.3M]
  ------------------
  183|  22.1k|      return TokenType::Plus;
  184|   103k|    case '-':
  ------------------
  |  Branch (184:5): [True: 103k, False: 26.2M]
  ------------------
  185|   103k|      return TokenType::Minus;
  186|  1.94k|    case '*':
  ------------------
  |  Branch (186:5): [True: 1.94k, False: 26.3M]
  ------------------
  187|  1.94k|      return TokenType::Star;
  188|  7.20k|    case '/':
  ------------------
  |  Branch (188:5): [True: 7.20k, False: 26.3M]
  ------------------
  189|  7.20k|      return TokenType::Slash;
  190|  3.36k|    case '&':
  ------------------
  |  Branch (190:5): [True: 3.36k, False: 26.3M]
  ------------------
  191|  3.36k|      return TokenType::Ampersand;
  192|  52.1k|    case '|':
  ------------------
  |  Branch (192:5): [True: 52.1k, False: 26.3M]
  ------------------
  193|  52.1k|      return TokenType::Pipe;
  194|  39.6k|    case '^':
  ------------------
  |  Branch (194:5): [True: 39.6k, False: 26.3M]
  ------------------
  195|  39.6k|      return TokenType::Caret;
  196|  99.8k|    case '~':
  ------------------
  |  Branch (196:5): [True: 99.8k, False: 26.2M]
  ------------------
  197|  99.8k|      return TokenType::Tilde;
  198|  68.0k|    case '!':
  ------------------
  |  Branch (198:5): [True: 68.0k, False: 26.2M]
  ------------------
  199|  68.0k|      return TokenType::Bang;
  200|   175k|    case '<':
  ------------------
  |  Branch (200:5): [True: 175k, False: 26.1M]
  ------------------
  201|   175k|      return TokenType::Less;
  202|  1.59M|    case '>':
  ------------------
  |  Branch (202:5): [True: 1.59M, False: 24.7M]
  ------------------
  203|  1.59M|      return TokenType::Greater;
  204|  63.2k|    case '=':
  ------------------
  |  Branch (204:5): [True: 63.2k, False: 26.2M]
  ------------------
  205|  63.2k|      return TokenType::Equal;
  206|  8.39k|    case '?':
  ------------------
  |  Branch (206:5): [True: 8.39k, False: 26.3M]
  ------------------
  207|  8.39k|      return TokenType::Question;
  208|  18.3k|    case ':':
  ------------------
  |  Branch (208:5): [True: 18.3k, False: 26.3M]
  ------------------
  209|  18.3k|      return TokenType::Colon;
  210|   161k|    case '(':
  ------------------
  |  Branch (210:5): [True: 161k, False: 26.1M]
  ------------------
  211|   161k|      return TokenType::LeftParen;
  212|  6.77k|    case ')':
  ------------------
  |  Branch (212:5): [True: 6.77k, False: 26.3M]
  ------------------
  213|  6.77k|      return TokenType::RightParen;
  214|   294k|    case ';':
  ------------------
  |  Branch (214:5): [True: 294k, False: 26.0M]
  ------------------
  215|   294k|      return TokenType::Semicolon;
  216|  23.6M|    default:
  ------------------
  |  Branch (216:5): [True: 23.6M, False: 2.71M]
  ------------------
  217|  23.6M|      return TokenType::Error;
  218|  26.3M|  }
  219|  26.3M|}

