LLVMFuzzerTestOneInput:
   13|  5.39k|{
   14|  5.39k|  if(size < 4)
  ------------------
  |  Branch (14:6): [True: 2, False: 5.39k]
  ------------------
   15|      2|  {
   16|      2|    return 0;
   17|      2|  }
   18|       |
   19|  5.39k|  FuzzedDataProvider fuzz_data(data, size);
   20|       |
   21|  5.39k|  try
   22|  5.39k|  {
   23|  5.39k|    BT::Ast::Environment env;
   24|  5.39k|    env.vars = BT::Blackboard::create();
   25|  5.39k|    env.enums = std::make_shared<BT::EnumsTable>();
   26|       |
   27|       |    // Add some test variables to the blackboard
   28|  5.39k|    env.vars->set("test_int", 42);
   29|  5.39k|    env.vars->set("test_double", 3.14);
   30|  5.39k|    env.vars->set("test_bool", true);
   31|  5.39k|    env.vars->set("test_string", std::string("test"));
   32|       |
   33|       |    // Add some test enums
   34|  5.39k|    (*env.enums)["RUNNING"] = 0;
   35|  5.39k|    (*env.enums)["SUCCESS"] = 1;
   36|  5.39k|    (*env.enums)["FAILURE"] = 2;
   37|       |
   38|  5.39k|    std::string script = fuzz_data.ConsumeRandomLengthString();
   39|       |
   40|  5.39k|    auto validation_result = BT::ValidateScript(script);
   41|       |
   42|  5.39k|    if(!validation_result)
  ------------------
  |  Branch (42:8): [True: 1.54k, False: 3.85k]
  ------------------
   43|  1.54k|    {
   44|  1.54k|      auto parsed_script = BT::ParseScript(script);
   45|  1.54k|      if(parsed_script)
  ------------------
  |  Branch (45:10): [True: 0, False: 1.54k]
  ------------------
   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.54k|    }
   67|       |
   68|  5.39k|    BT::ParseScriptAndExecute(env, script);
   69|  5.39k|  }
   70|  5.39k|  catch(const std::exception&)  // NOLINT(bugprone-empty-catch)
   71|  5.39k|  {
   72|       |    // Intentionally empty - fuzzer expects exceptions
   73|    210|  }
   74|       |
   75|  5.39k|  return 0;
   76|  5.39k|}

_ZN2BT23GetAnyFromStringFunctorIiEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  234|  5.39k|{
  235|       |  if constexpr(std::is_constructible_v<StringView, T>)
  236|       |  {
  237|       |    return [](StringView str) { return Any(str); };
  238|       |  }
  239|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  240|       |  {
  241|       |    return {};
  242|       |  }
  243|       |  else
  244|  5.39k|  {
  245|  5.39k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  246|  5.39k|  }
  247|  5.39k|}
_ZN2BT8PortInfoC2ENS_13PortDirectionESt10type_indexSt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEE:
  431|  16.1k|    : TypeInfo(type_info, conv), direction_(direction)
  432|  16.1k|  {}
_ZN2BT8TypeInfoC2ESt10type_indexSt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEE:
  389|  16.1k|    : type_info_(type_info), converter_(conv), type_str_(BT::demangle(type_info))
  390|  16.1k|  {}
_ZN2BT23GetAnyFromStringFunctorIdEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  234|  5.39k|{
  235|       |  if constexpr(std::is_constructible_v<StringView, T>)
  236|       |  {
  237|       |    return [](StringView str) { return Any(str); };
  238|       |  }
  239|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  240|       |  {
  241|       |    return {};
  242|       |  }
  243|       |  else
  244|  5.39k|  {
  245|  5.39k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  246|  5.39k|  }
  247|  5.39k|}
_ZN2BT23GetAnyFromStringFunctorIbEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  234|  5.39k|{
  235|       |  if constexpr(std::is_constructible_v<StringView, T>)
  236|       |  {
  237|       |    return [](StringView str) { return Any(str); };
  238|       |  }
  239|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  240|       |  {
  241|       |    return {};
  242|       |  }
  243|       |  else
  244|  5.39k|  {
  245|  5.39k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  246|  5.39k|  }
  247|  5.39k|}
_ZN2BT8PortInfoC2ENS_13PortDirectionE:
  427|  13.7k|    : TypeInfo(), direction_(direction)
  428|  13.7k|  {}
_ZN2BT8TypeInfoC2Ev:
  385|  13.7k|  TypeInfo() : type_info_(typeid(AnyTypeAllowed)), type_str_("AnyTypeAllowed")
  386|  13.7k|  {}
_ZNK2BT8TypeInfo9converterEv:
  413|    664|  {
  414|    664|    return converter_;
  415|    664|  }

_ZN2BT10Blackboard6createESt10shared_ptrIS0_E:
   79|  5.39k|  {
   80|  5.39k|    return std::shared_ptr<Blackboard>(new Blackboard(parent));
   81|  5.39k|  }
_ZN2BT10BlackboardC2ESt10shared_ptrIS0_E:
   45|  5.39k|  Blackboard(Blackboard::Ptr parent) : parent_bb_(parent)
   46|  5.39k|  {}
_ZN2BT10BlackboardD2Ev:
   83|  5.39k|  virtual ~Blackboard() = default;
_ZN2BT10Blackboard3setIiEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  287|  5.39k|{
  288|  5.39k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (288:6): [True: 0, False: 5.39k]
  ------------------
  289|      0|  {
  290|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  291|      0|    return;
  292|      0|  }
  293|       |  // getEntry() follows the remapping to the parent blackboard, exactly like
  294|       |  // the readers do. A key that resolves to an existing entry (local or
  295|       |  // remapped) must go through the type check below: createEntryImpl() would
  296|       |  // follow the same remapping and return the pre-existing entry, and writing
  297|       |  // to it blindly bypasses the type lock and the string conversion.
  298|  5.39k|  auto entry_ptr = getEntry(key);
  299|  5.39k|  if(!entry_ptr)
  ------------------
  |  Branch (299:6): [True: 5.39k, False: 0]
  ------------------
  300|  5.39k|  {
  301|       |    // create a new entry
  302|  5.39k|    Any new_value(value);
  303|  5.39k|    std::shared_ptr<Blackboard::Entry> entry;
  304|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  305|       |    if constexpr(std::is_same_v<std::string, T>)
  306|       |    {
  307|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  308|       |    }
  309|       |    else
  310|  5.39k|    {
  311|  5.39k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  312|  5.39k|                        GetAnyFromStringFunctor<T>());
  313|  5.39k|      entry = createEntryImpl(key, new_port);
  314|  5.39k|    }
  315|       |
  316|       |    // Lock entry_mutex before writing to prevent data races with
  317|       |    // concurrent readers (BUG-1/BUG-8 fix).
  318|  5.39k|    std::scoped_lock entry_lock(entry->entry_mutex);
  319|  5.39k|    entry->value = new_value;
  320|  5.39k|    entry->sequence_id++;
  321|  5.39k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  322|  5.39k|  }
  323|      0|  else
  324|      0|  {
  325|       |    // this is not the first time we set this entry, we need to check
  326|       |    // if the type is the same or not.
  327|      0|    Entry& entry = *entry_ptr;
  328|       |
  329|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  330|       |
  331|      0|    Any& previous_any = entry.value;
  332|      0|    Any new_value(value);
  333|       |
  334|       |    // special case: entry exists but it is not strongly typed... yet
  335|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (335:8): [True: 0, False: 0]
  ------------------
  336|      0|    {
  337|       |      // Use the new type to create a new entry that is strongly typed.
  338|      0|      entry.info = TypeInfo::Create<T>();
  339|      0|      entry.sequence_id++;
  340|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  341|      0|      previous_any = std::move(new_value);
  342|      0|      return;
  343|      0|    }
  344|       |
  345|      0|    std::type_index previous_type = entry.info.type();
  346|       |
  347|       |    // check type mismatch
  348|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:55): [True: 0, False: 0]
  ------------------
  349|      0|    {
  350|      0|      bool mismatching = true;
  351|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (351:10): [Folded, False: 0]
  ------------------
  352|      0|      {
  353|      0|        Any any_from_string = entry.info.parseString(value);
  354|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|          new_value = std::move(any_from_string);
  358|      0|        }
  359|      0|      }
  360|       |      // check if we are doing a safe cast between numbers
  361|       |      // for instance, it is safe to use int(100) to set
  362|       |      // a uint8_t port, but not int(-42) or int(300)
  363|       |      if constexpr(std::is_arithmetic_v<T>)
  364|      0|      {
  365|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (365:12): [True: 0, False: 0]
  |  Branch (365:27): [True: 0, False: 0]
  ------------------
  366|      0|        {
  367|      0|          mismatching = false;
  368|      0|        }
  369|      0|      }
  370|       |
  371|      0|      if(mismatching)
  ------------------
  |  Branch (371:10): [True: 0, False: 0]
  ------------------
  372|      0|      {
  373|      0|        debugMessage();
  374|       |
  375|      0|        auto msg = StrCat("Blackboard::set(", key,
  376|      0|                          "): once declared, "
  377|      0|                          "the type of a port shall not change. "
  378|      0|                          "Previously declared type [",
  379|      0|                          BT::demangle(previous_type), "], current type [",
  380|      0|                          BT::demangle(typeid(T)), "]");
  381|      0|        throw LogicError(msg);
  382|      0|      }
  383|      0|    }
  384|       |    // if doing set<BT::Any>, skip type check
  385|       |    if constexpr(std::is_same_v<Any, T>)
  386|       |    {
  387|       |      previous_any = new_value;
  388|       |    }
  389|       |    else
  390|      0|    {
  391|       |      // copy only if the type is compatible
  392|      0|      new_value.copyInto(previous_any);
  393|      0|    }
  394|      0|    entry.sequence_id++;
  395|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  396|      0|  }
  397|  5.39k|}
_ZN2BT10Blackboard3setIdEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  287|  5.39k|{
  288|  5.39k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (288:6): [True: 0, False: 5.39k]
  ------------------
  289|      0|  {
  290|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  291|      0|    return;
  292|      0|  }
  293|       |  // getEntry() follows the remapping to the parent blackboard, exactly like
  294|       |  // the readers do. A key that resolves to an existing entry (local or
  295|       |  // remapped) must go through the type check below: createEntryImpl() would
  296|       |  // follow the same remapping and return the pre-existing entry, and writing
  297|       |  // to it blindly bypasses the type lock and the string conversion.
  298|  5.39k|  auto entry_ptr = getEntry(key);
  299|  5.39k|  if(!entry_ptr)
  ------------------
  |  Branch (299:6): [True: 5.39k, False: 0]
  ------------------
  300|  5.39k|  {
  301|       |    // create a new entry
  302|  5.39k|    Any new_value(value);
  303|  5.39k|    std::shared_ptr<Blackboard::Entry> entry;
  304|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  305|       |    if constexpr(std::is_same_v<std::string, T>)
  306|       |    {
  307|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  308|       |    }
  309|       |    else
  310|  5.39k|    {
  311|  5.39k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  312|  5.39k|                        GetAnyFromStringFunctor<T>());
  313|  5.39k|      entry = createEntryImpl(key, new_port);
  314|  5.39k|    }
  315|       |
  316|       |    // Lock entry_mutex before writing to prevent data races with
  317|       |    // concurrent readers (BUG-1/BUG-8 fix).
  318|  5.39k|    std::scoped_lock entry_lock(entry->entry_mutex);
  319|  5.39k|    entry->value = new_value;
  320|  5.39k|    entry->sequence_id++;
  321|  5.39k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  322|  5.39k|  }
  323|      0|  else
  324|      0|  {
  325|       |    // this is not the first time we set this entry, we need to check
  326|       |    // if the type is the same or not.
  327|      0|    Entry& entry = *entry_ptr;
  328|       |
  329|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  330|       |
  331|      0|    Any& previous_any = entry.value;
  332|      0|    Any new_value(value);
  333|       |
  334|       |    // special case: entry exists but it is not strongly typed... yet
  335|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (335:8): [True: 0, False: 0]
  ------------------
  336|      0|    {
  337|       |      // Use the new type to create a new entry that is strongly typed.
  338|      0|      entry.info = TypeInfo::Create<T>();
  339|      0|      entry.sequence_id++;
  340|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  341|      0|      previous_any = std::move(new_value);
  342|      0|      return;
  343|      0|    }
  344|       |
  345|      0|    std::type_index previous_type = entry.info.type();
  346|       |
  347|       |    // check type mismatch
  348|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:55): [True: 0, False: 0]
  ------------------
  349|      0|    {
  350|      0|      bool mismatching = true;
  351|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (351:10): [Folded, False: 0]
  ------------------
  352|      0|      {
  353|      0|        Any any_from_string = entry.info.parseString(value);
  354|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|          new_value = std::move(any_from_string);
  358|      0|        }
  359|      0|      }
  360|       |      // check if we are doing a safe cast between numbers
  361|       |      // for instance, it is safe to use int(100) to set
  362|       |      // a uint8_t port, but not int(-42) or int(300)
  363|       |      if constexpr(std::is_arithmetic_v<T>)
  364|      0|      {
  365|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (365:12): [True: 0, False: 0]
  |  Branch (365:27): [True: 0, False: 0]
  ------------------
  366|      0|        {
  367|      0|          mismatching = false;
  368|      0|        }
  369|      0|      }
  370|       |
  371|      0|      if(mismatching)
  ------------------
  |  Branch (371:10): [True: 0, False: 0]
  ------------------
  372|      0|      {
  373|      0|        debugMessage();
  374|       |
  375|      0|        auto msg = StrCat("Blackboard::set(", key,
  376|      0|                          "): once declared, "
  377|      0|                          "the type of a port shall not change. "
  378|      0|                          "Previously declared type [",
  379|      0|                          BT::demangle(previous_type), "], current type [",
  380|      0|                          BT::demangle(typeid(T)), "]");
  381|      0|        throw LogicError(msg);
  382|      0|      }
  383|      0|    }
  384|       |    // if doing set<BT::Any>, skip type check
  385|       |    if constexpr(std::is_same_v<Any, T>)
  386|       |    {
  387|       |      previous_any = new_value;
  388|       |    }
  389|       |    else
  390|      0|    {
  391|       |      // copy only if the type is compatible
  392|      0|      new_value.copyInto(previous_any);
  393|      0|    }
  394|      0|    entry.sequence_id++;
  395|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  396|      0|  }
  397|  5.39k|}
_ZN2BT10Blackboard3setIbEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  287|  5.39k|{
  288|  5.39k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (288:6): [True: 0, False: 5.39k]
  ------------------
  289|      0|  {
  290|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  291|      0|    return;
  292|      0|  }
  293|       |  // getEntry() follows the remapping to the parent blackboard, exactly like
  294|       |  // the readers do. A key that resolves to an existing entry (local or
  295|       |  // remapped) must go through the type check below: createEntryImpl() would
  296|       |  // follow the same remapping and return the pre-existing entry, and writing
  297|       |  // to it blindly bypasses the type lock and the string conversion.
  298|  5.39k|  auto entry_ptr = getEntry(key);
  299|  5.39k|  if(!entry_ptr)
  ------------------
  |  Branch (299:6): [True: 5.39k, False: 0]
  ------------------
  300|  5.39k|  {
  301|       |    // create a new entry
  302|  5.39k|    Any new_value(value);
  303|  5.39k|    std::shared_ptr<Blackboard::Entry> entry;
  304|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  305|       |    if constexpr(std::is_same_v<std::string, T>)
  306|       |    {
  307|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  308|       |    }
  309|       |    else
  310|  5.39k|    {
  311|  5.39k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  312|  5.39k|                        GetAnyFromStringFunctor<T>());
  313|  5.39k|      entry = createEntryImpl(key, new_port);
  314|  5.39k|    }
  315|       |
  316|       |    // Lock entry_mutex before writing to prevent data races with
  317|       |    // concurrent readers (BUG-1/BUG-8 fix).
  318|  5.39k|    std::scoped_lock entry_lock(entry->entry_mutex);
  319|  5.39k|    entry->value = new_value;
  320|  5.39k|    entry->sequence_id++;
  321|  5.39k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  322|  5.39k|  }
  323|      0|  else
  324|      0|  {
  325|       |    // this is not the first time we set this entry, we need to check
  326|       |    // if the type is the same or not.
  327|      0|    Entry& entry = *entry_ptr;
  328|       |
  329|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  330|       |
  331|      0|    Any& previous_any = entry.value;
  332|      0|    Any new_value(value);
  333|       |
  334|       |    // special case: entry exists but it is not strongly typed... yet
  335|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (335:8): [True: 0, False: 0]
  ------------------
  336|      0|    {
  337|       |      // Use the new type to create a new entry that is strongly typed.
  338|      0|      entry.info = TypeInfo::Create<T>();
  339|      0|      entry.sequence_id++;
  340|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  341|      0|      previous_any = std::move(new_value);
  342|      0|      return;
  343|      0|    }
  344|       |
  345|      0|    std::type_index previous_type = entry.info.type();
  346|       |
  347|       |    // check type mismatch
  348|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:55): [True: 0, False: 0]
  ------------------
  349|      0|    {
  350|      0|      bool mismatching = true;
  351|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (351:10): [Folded, False: 0]
  ------------------
  352|      0|      {
  353|      0|        Any any_from_string = entry.info.parseString(value);
  354|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|          new_value = std::move(any_from_string);
  358|      0|        }
  359|      0|      }
  360|       |      // check if we are doing a safe cast between numbers
  361|       |      // for instance, it is safe to use int(100) to set
  362|       |      // a uint8_t port, but not int(-42) or int(300)
  363|       |      if constexpr(std::is_arithmetic_v<T>)
  364|      0|      {
  365|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (365:12): [True: 0, False: 0]
  |  Branch (365:27): [True: 0, False: 0]
  ------------------
  366|      0|        {
  367|      0|          mismatching = false;
  368|      0|        }
  369|      0|      }
  370|       |
  371|      0|      if(mismatching)
  ------------------
  |  Branch (371:10): [True: 0, False: 0]
  ------------------
  372|      0|      {
  373|      0|        debugMessage();
  374|       |
  375|      0|        auto msg = StrCat("Blackboard::set(", key,
  376|      0|                          "): once declared, "
  377|      0|                          "the type of a port shall not change. "
  378|      0|                          "Previously declared type [",
  379|      0|                          BT::demangle(previous_type), "], current type [",
  380|      0|                          BT::demangle(typeid(T)), "]");
  381|      0|        throw LogicError(msg);
  382|      0|      }
  383|      0|    }
  384|       |    // if doing set<BT::Any>, skip type check
  385|       |    if constexpr(std::is_same_v<Any, T>)
  386|       |    {
  387|       |      previous_any = new_value;
  388|       |    }
  389|       |    else
  390|      0|    {
  391|       |      // copy only if the type is compatible
  392|      0|      new_value.copyInto(previous_any);
  393|      0|    }
  394|      0|    entry.sequence_id++;
  395|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  396|      0|  }
  397|  5.39k|}
_ZN2BT10Blackboard3setINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvRKS7_RKT_:
  287|  5.39k|{
  288|  5.39k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (288:6): [True: 0, False: 5.39k]
  ------------------
  289|      0|  {
  290|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  291|      0|    return;
  292|      0|  }
  293|       |  // getEntry() follows the remapping to the parent blackboard, exactly like
  294|       |  // the readers do. A key that resolves to an existing entry (local or
  295|       |  // remapped) must go through the type check below: createEntryImpl() would
  296|       |  // follow the same remapping and return the pre-existing entry, and writing
  297|       |  // to it blindly bypasses the type lock and the string conversion.
  298|  5.39k|  auto entry_ptr = getEntry(key);
  299|  5.39k|  if(!entry_ptr)
  ------------------
  |  Branch (299:6): [True: 5.39k, False: 0]
  ------------------
  300|  5.39k|  {
  301|       |    // create a new entry
  302|  5.39k|    Any new_value(value);
  303|  5.39k|    std::shared_ptr<Blackboard::Entry> entry;
  304|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  305|       |    if constexpr(std::is_same_v<std::string, T>)
  306|  5.39k|    {
  307|  5.39k|      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  308|       |    }
  309|       |    else
  310|       |    {
  311|       |      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  312|       |                        GetAnyFromStringFunctor<T>());
  313|       |      entry = createEntryImpl(key, new_port);
  314|       |    }
  315|       |
  316|       |    // Lock entry_mutex before writing to prevent data races with
  317|       |    // concurrent readers (BUG-1/BUG-8 fix).
  318|  5.39k|    std::scoped_lock entry_lock(entry->entry_mutex);
  319|  5.39k|    entry->value = new_value;
  320|  5.39k|    entry->sequence_id++;
  321|  5.39k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  322|  5.39k|  }
  323|      0|  else
  324|      0|  {
  325|       |    // this is not the first time we set this entry, we need to check
  326|       |    // if the type is the same or not.
  327|      0|    Entry& entry = *entry_ptr;
  328|       |
  329|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  330|       |
  331|      0|    Any& previous_any = entry.value;
  332|      0|    Any new_value(value);
  333|       |
  334|       |    // special case: entry exists but it is not strongly typed... yet
  335|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (335:8): [True: 0, False: 0]
  ------------------
  336|      0|    {
  337|       |      // Use the new type to create a new entry that is strongly typed.
  338|      0|      entry.info = TypeInfo::Create<T>();
  339|      0|      entry.sequence_id++;
  340|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  341|      0|      previous_any = std::move(new_value);
  342|      0|      return;
  343|      0|    }
  344|       |
  345|      0|    std::type_index previous_type = entry.info.type();
  346|       |
  347|       |    // check type mismatch
  348|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:8): [True: 0, False: 0]
  |  Branch (348:55): [True: 0, False: 0]
  ------------------
  349|      0|    {
  350|      0|      bool mismatching = true;
  351|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (351:10): [True: 0, Folded]
  ------------------
  352|      0|      {
  353|      0|        Any any_from_string = entry.info.parseString(value);
  354|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|          new_value = std::move(any_from_string);
  358|      0|        }
  359|      0|      }
  360|       |      // check if we are doing a safe cast between numbers
  361|       |      // for instance, it is safe to use int(100) to set
  362|       |      // a uint8_t port, but not int(-42) or int(300)
  363|       |      if constexpr(std::is_arithmetic_v<T>)
  364|       |      {
  365|       |        if(mismatching && isCastingSafe(previous_type, value))
  366|       |        {
  367|       |          mismatching = false;
  368|       |        }
  369|       |      }
  370|       |
  371|      0|      if(mismatching)
  ------------------
  |  Branch (371:10): [True: 0, False: 0]
  ------------------
  372|      0|      {
  373|      0|        debugMessage();
  374|       |
  375|      0|        auto msg = StrCat("Blackboard::set(", key,
  376|      0|                          "): once declared, "
  377|      0|                          "the type of a port shall not change. "
  378|      0|                          "Previously declared type [",
  379|      0|                          BT::demangle(previous_type), "], current type [",
  380|      0|                          BT::demangle(typeid(T)), "]");
  381|      0|        throw LogicError(msg);
  382|      0|      }
  383|      0|    }
  384|       |    // if doing set<BT::Any>, skip type check
  385|       |    if constexpr(std::is_same_v<Any, T>)
  386|       |    {
  387|       |      previous_any = new_value;
  388|       |    }
  389|       |    else
  390|      0|    {
  391|       |      // copy only if the type is compatible
  392|      0|      new_value.copyInto(previous_any);
  393|      0|    }
  394|      0|    entry.sequence_id++;
  395|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  396|      0|  }
  397|  5.39k|}
_ZN2BT10Blackboard5EntryC2ERKNS_8TypeInfoE:
   65|  29.9k|    Entry(const TypeInfo& _info) : info(_info)
   66|  29.9k|    {}
_ZN2BT10Blackboard5EntryD2Ev:
   68|  29.9k|    ~Entry() = default;

_ZNK4linb3any4typeEv:
  176|  2.71M|    {
  177|  2.71M|        return empty()? typeid(void) : this->vtable->type();
  ------------------
  |  Branch (177:16): [True: 4, False: 2.71M]
  ------------------
  178|  2.71M|    }
_ZNK4linb3any5emptyEv:
  169|  12.4M|    {
  170|  12.4M|        return this->vtable == nullptr;
  171|  12.4M|    }
_ZN4linb3anyC2Ev:
   72|  90.0k|        vtable(nullptr)
   73|  90.0k|    {
   74|  90.0k|    }
_ZN4linb3anyD2Ev:
  100|  5.29M|    {
  101|  5.29M|        this->clear();
  102|  5.29M|    }
_ZN4linb3any5clearEv:
  159|  5.29M|    {
  160|  5.29M|        if(!empty())
  ------------------
  |  Branch (160:12): [True: 3.62M, False: 1.67M]
  ------------------
  161|  3.62M|        {
  162|  3.62M|            this->vtable->destroy(storage);
  163|  3.62M|            this->vtable = nullptr;
  164|  3.62M|        }
  165|  5.29M|    }
_ZN4linb8any_castIdEET_RKNS_3anyE:
  468|   149k|{
  469|   149k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|   149k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|   149k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 149k]
  ------------------
  472|   149k|#endif
  473|   149k|    return *p;
  474|   149k|}
_ZN4linb8any_castIKdEEPKT_PKNS_3anyE:
  510|   149k|{
  511|   149k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|   149k|#ifndef ANY_IMPL_NO_RTTI
  514|   149k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 149k, False: 0]
  |  Branch (514:20): [True: 149k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|   149k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|   149k|}
_ZNK4linb3any8is_typedERKSt9type_info:
  355|   548k|    {
  356|   548k|        return is_same(this->type(), t);
  357|   548k|    }
_ZN4linb3any7is_sameERKSt9type_infoS3_:
  368|   548k|    {
  369|       |#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
  370|       |        return &a == &b;
  371|       |#else
  372|   548k|        return a == b;
  373|   548k|#endif
  374|   548k|    }
_ZNK4linb3any4castIKdEEPKT_v:
  380|   149k|    {
  381|   149k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 149k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|   149k|            reinterpret_cast<const T*>(&storage.stack);
  384|   149k|    }
_ZN4linb8any_castIN7SafeAny12SimpleStringEEET_RKNS_3anyE:
  468|   147k|{
  469|   147k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|   147k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|   147k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 147k]
  ------------------
  472|   147k|#endif
  473|   147k|    return *p;
  474|   147k|}
_ZN4linb8any_castIKN7SafeAny12SimpleStringEEEPKT_PKNS_3anyE:
  510|   147k|{
  511|   147k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|   147k|#ifndef ANY_IMPL_NO_RTTI
  514|   147k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 147k, False: 0]
  |  Branch (514:20): [True: 147k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|   147k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|   147k|}
_ZNK4linb3any4castIKN7SafeAny12SimpleStringEEEPKT_v:
  380|   147k|    {
  381|   147k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 147k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|   147k|            reinterpret_cast<const T*>(&storage.stack);
  384|   147k|    }
_ZN4linb8any_castIlEET_RKNS_3anyE:
  468|   252k|{
  469|   252k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|   252k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|   252k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 252k]
  ------------------
  472|   252k|#endif
  473|   252k|    return *p;
  474|   252k|}
_ZN4linb8any_castIKlEEPKT_PKNS_3anyE:
  510|   252k|{
  511|   252k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|   252k|#ifndef ANY_IMPL_NO_RTTI
  514|   252k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 252k, False: 0]
  |  Branch (514:20): [True: 252k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|   252k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|   252k|}
_ZNK4linb3any4castIKlEEPKT_v:
  380|   252k|    {
  381|   252k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 252k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|   252k|            reinterpret_cast<const T*>(&storage.stack);
  384|   252k|    }
_ZN4linb3anyC2IlvEEOT_:
  110|  1.34M|    {
  111|  1.34M|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|  1.34M|            "T shall satisfy the CopyConstructible requirements.");
  113|  1.34M|        this->construct(std::forward<ValueType>(value));
  114|  1.34M|    }
_ZN4linb3any9constructIlEEvOT_:
  439|  1.34M|    {
  440|  1.34M|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|  1.34M|        this->vtable = vtable_for_type<T>();
  443|       |
  444|  1.34M|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|  1.34M|    }
_ZN4linb3any15vtable_for_typeIlEEPNS0_11vtable_typeEv:
  333|  1.34M|    {
  334|  1.34M|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|  1.34M|        static vtable_type table = {
  336|  1.34M|#ifndef ANY_IMPL_NO_RTTI
  337|  1.34M|            VTableType::type,
  338|  1.34M|#endif
  339|  1.34M|            VTableType::destroy,
  340|  1.34M|            VTableType::copy, VTableType::move,
  341|  1.34M|            VTableType::swap,
  342|  1.34M|        };
  343|  1.34M|        return &table;
  344|  1.34M|    }
_ZN4linb3any12vtable_stackIlE4typeEv:
  289|  1.15M|        {
  290|  1.15M|            return typeid(T);
  291|  1.15M|        }
_ZN4linb3any12vtable_stackIlE7destroyERNS0_13storage_unionE:
  295|  4.38M|        {
  296|  4.38M|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|  4.38M|        }
_ZN4linb3any12vtable_stackIlE4copyERKNS0_13storage_unionERS3_:
  300|  1.53M|        {
  301|  1.53M|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|  1.53M|        }
_ZN4linb3any12vtable_stackIlE4moveERNS0_13storage_unionES4_:
  305|  1.50M|        {
  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.50M|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|  1.50M|            destroy(src);
  310|  1.50M|        }
_ZN4linb3any12vtable_stackIlE4swapERNS0_13storage_unionES4_:
  313|  28.2k|        {
  314|  28.2k|            storage_union tmp_storage;
  315|  28.2k|            move(rhs, tmp_storage);
  316|  28.2k|            move(lhs, rhs);
  317|  28.2k|            move(tmp_storage, lhs);
  318|  28.2k|        }
_ZN4linb3any12do_constructIllEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|  1.34M|    {
  432|  1.34M|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|  1.34M|    }
_ZN4linb3anyaSERKS0_:
  129|   116k|    {
  130|   116k|        any(rhs).swap(*this);
  131|   116k|        return *this;
  132|   116k|    }
_ZN4linb3anyC2ERKS0_:
   78|  1.91M|        vtable(rhs.vtable)
   79|  1.91M|    {
   80|  1.91M|        if(!rhs.empty())
  ------------------
  |  Branch (80:12): [True: 1.91M, False: 206]
  ------------------
   81|  1.91M|        {
   82|  1.91M|            rhs.vtable->copy(rhs.storage, this->storage);
   83|  1.91M|        }
   84|  1.91M|    }
_ZN4linb3any4swapERS0_:
  183|   157k|    {
  184|   157k|        if(this->vtable != rhs.vtable)
  ------------------
  |  Branch (184:12): [True: 75.7k, False: 81.2k]
  ------------------
  185|  75.7k|        {
  186|  75.7k|            any tmp(std::move(rhs));
  187|       |
  188|       |            // move from *this to rhs.
  189|  75.7k|            rhs.vtable = this->vtable;
  190|  75.7k|            if(this->vtable != nullptr)
  ------------------
  |  Branch (190:16): [True: 75.7k, False: 0]
  ------------------
  191|  75.7k|            {
  192|  75.7k|                this->vtable->move(this->storage, rhs.storage);
  193|       |                //this->vtable = nullptr; -- unneeded, see below
  194|  75.7k|            }
  195|       |
  196|       |            // move from tmp (previously rhs) to *this.
  197|  75.7k|            this->vtable = tmp.vtable;
  198|  75.7k|            if(tmp.vtable != nullptr)
  ------------------
  |  Branch (198:16): [True: 47.2k, False: 28.5k]
  ------------------
  199|  47.2k|            {
  200|  47.2k|                tmp.vtable->move(tmp.storage, this->storage);
  201|  47.2k|                tmp.vtable = nullptr;
  202|  47.2k|            }
  203|  75.7k|        }
  204|  81.2k|        else // same types
  205|  81.2k|        {
  206|  81.2k|            if(this->vtable != nullptr)
  ------------------
  |  Branch (206:16): [True: 51.2k, False: 29.9k]
  ------------------
  207|  51.2k|                this->vtable->swap(this->storage, rhs.storage);
  208|  81.2k|        }
  209|   157k|    }
_ZN4linb3anyC2EOS0_:
   89|  1.58M|        vtable(rhs.vtable)
   90|  1.58M|    {
   91|  1.58M|        if(!rhs.empty())
  ------------------
  |  Branch (91:12): [True: 1.55M, False: 28.5k]
  ------------------
   92|  1.55M|        {
   93|  1.55M|            rhs.vtable->move(rhs.storage, this->storage);
   94|  1.55M|            rhs.vtable = nullptr;
   95|  1.55M|        }
   96|  1.58M|    }
_ZN4linb3anyaSEOS0_:
  139|  39.1k|    {
  140|  39.1k|        std::move(rhs).swap(*this);
  141|  39.1k|        return *this;
  142|  39.1k|    }
_ZN4linb3anyaSIlvEERS0_OT_:
  150|    863|    {
  151|    863|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  152|    863|            "T shall satisfy the CopyConstructible requirements.");
  153|    863|        any(std::forward<ValueType>(value)).swap(*this);
  154|    863|        return *this;
  155|    863|    }
_ZN4linb3anyaSIdvEERS0_OT_:
  150|    195|    {
  151|    195|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  152|    195|            "T shall satisfy the CopyConstructible requirements.");
  153|    195|        any(std::forward<ValueType>(value)).swap(*this);
  154|    195|        return *this;
  155|    195|    }
_ZN4linb3anyC2IdvEEOT_:
  110|    195|    {
  111|    195|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|    195|            "T shall satisfy the CopyConstructible requirements.");
  113|    195|        this->construct(std::forward<ValueType>(value));
  114|    195|    }
_ZN4linb3any9constructIdEEvOT_:
  439|    195|    {
  440|    195|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|    195|        this->vtable = vtable_for_type<T>();
  443|       |
  444|    195|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|    195|    }
_ZN4linb3any15vtable_for_typeIdEEPNS0_11vtable_typeEv:
  333|   183k|    {
  334|   183k|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|   183k|        static vtable_type table = {
  336|   183k|#ifndef ANY_IMPL_NO_RTTI
  337|   183k|            VTableType::type,
  338|   183k|#endif
  339|   183k|            VTableType::destroy,
  340|   183k|            VTableType::copy, VTableType::move,
  341|   183k|            VTableType::swap,
  342|   183k|        };
  343|   183k|        return &table;
  344|   183k|    }
_ZN4linb3any12vtable_stackIdE4typeEv:
  289|   697k|        {
  290|   697k|            return typeid(T);
  291|   697k|        }
_ZN4linb3any12vtable_stackIdE7destroyERNS0_13storage_unionE:
  295|   228k|        {
  296|   228k|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|   228k|        }
_ZN4linb3any12vtable_stackIdE4copyERKNS0_13storage_unionERS3_:
  300|  19.5k|        {
  301|  19.5k|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|  19.5k|        }
_ZN4linb3any12vtable_stackIdE4moveERNS0_13storage_unionES4_:
  305|  25.1k|        {
  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.1k|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|  25.1k|            destroy(src);
  310|  25.1k|        }
_ZN4linb3any12vtable_stackIdE4swapERNS0_13storage_unionES4_:
  313|  3.05k|        {
  314|  3.05k|            storage_union tmp_storage;
  315|  3.05k|            move(rhs, tmp_storage);
  316|  3.05k|            move(lhs, rhs);
  317|  3.05k|            move(tmp_storage, lhs);
  318|  3.05k|        }
_ZN4linb3any12do_constructIddEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|    195|    {
  432|    195|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|    195|    }
_ZN4linb3anyC2IRKdvEEOT_:
  110|   183k|    {
  111|   183k|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|   183k|            "T shall satisfy the CopyConstructible requirements.");
  113|   183k|        this->construct(std::forward<ValueType>(value));
  114|   183k|    }
_ZN4linb3any9constructIRKdEEvOT_:
  439|   183k|    {
  440|   183k|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|   183k|        this->vtable = vtable_for_type<T>();
  443|       |
  444|   183k|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|   183k|    }
_ZN4linb3any12do_constructIRKddEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|   183k|    {
  432|   183k|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|   183k|    }
_ZN4linb3anyC2IN7SafeAny12SimpleStringEvEEOT_:
  110|   183k|    {
  111|   183k|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|   183k|            "T shall satisfy the CopyConstructible requirements.");
  113|   183k|        this->construct(std::forward<ValueType>(value));
  114|   183k|    }
_ZN4linb3any9constructIN7SafeAny12SimpleStringEEEvOT_:
  439|   183k|    {
  440|   183k|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|   183k|        this->vtable = vtable_for_type<T>();
  443|       |
  444|   183k|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|   183k|    }
_ZN4linb3any15vtable_for_typeIN7SafeAny12SimpleStringEEEPNS0_11vtable_typeEv:
  333|   183k|    {
  334|   183k|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|   183k|        static vtable_type table = {
  336|   183k|#ifndef ANY_IMPL_NO_RTTI
  337|   183k|            VTableType::type,
  338|   183k|#endif
  339|   183k|            VTableType::destroy,
  340|   183k|            VTableType::copy, VTableType::move,
  341|   183k|            VTableType::swap,
  342|   183k|        };
  343|   183k|        return &table;
  344|   183k|    }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4typeEv:
  289|   863k|        {
  290|   863k|            return typeid(T);
  291|   863k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE7destroyERNS0_13storage_unionE:
  295|   846k|        {
  296|   846k|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|   846k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4copyERKNS0_13storage_unionERS5_:
  300|   357k|        {
  301|   357k|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|   357k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4moveERNS0_13storage_unionES6_:
  305|   305k|        {
  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|   305k|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|   305k|            destroy(src);
  310|   305k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4swapERNS0_13storage_unionES6_:
  313|  19.9k|        {
  314|  19.9k|            storage_union tmp_storage;
  315|  19.9k|            move(rhs, tmp_storage);
  316|  19.9k|            move(lhs, rhs);
  317|  19.9k|            move(tmp_storage, lhs);
  318|  19.9k|        }
_ZN4linb3any12do_constructIN7SafeAny12SimpleStringES3_EENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|   183k|    {
  432|   183k|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|   183k|    }

_ZNK6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  5.39k|    {
 2192|  5.39k|        return has_value();
 2193|  5.39k|    }
_ZNK6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  10.7k|    {
 2197|  10.7k|        return contained.has_value();
 2198|  10.7k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  10.7k|    {
  787|  10.7k|        return m_has_value;
  788|  10.7k|    }
_ZNK6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  6.94k|    {
 2192|  6.94k|        return has_value();
 2193|  6.94k|    }
_ZNK6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  17.7k|    {
 2197|  17.7k|        return contained.has_value();
 2198|  17.7k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  17.7k|    {
  787|  17.7k|        return m_has_value;
  788|  17.7k|    }
_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|   486k|    : contained( true )
 1928|   486k|    {
 1929|   486k|        contained.construct_value( std::forward<U>( value ) );
 1930|   486k|    }
_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|   486k|    {
  688|   486k|        new( &m_value ) value_type( std::move( e ) );
  689|   486k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRA39_KcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS7_:
 1566|    168|{
 1567|    168|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|    168|}
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IRA39_S2_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS9_E4typeESt10in_place_tEE5valuentsr3std7is_sameISD_S4_EE5valueEiE4typeELi0EEEOS9_:
 1237|    168|    : m_error( std::forward<E2>( error ) )
 1238|    168|    {}
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS7_OT_EE5valuesr3std14is_convertibleISE_S7_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISD_EE:
 1977|    168|    : contained( false )
 1978|    168|    {
 1979|    168|        contained.construct_error( std::move( error.error() ) );
 1980|    168|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOS8_:
  714|    336|    {
  715|    336|        new( &m_error ) error_type( std::move( e ) );
  716|    336|    }
_ZNR6nonstd13expected_lite15unexpected_typeIPKcE5errorEv:
 1334|  5.79k|    {
 1335|  5.79k|        return m_error;
 1336|  5.79k|    }
_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|  49.2k|    : contained( true )
 1928|  49.2k|    {
 1929|  49.2k|        contained.construct_value( std::forward<U>( value ) );
 1930|  49.2k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueERKd:
  682|  49.2k|    {
  683|  49.2k|        new( &m_value ) value_type( e );
  684|  49.2k|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2EOS8_:
 1793|    168|    nsel_constexpr14 expected( expected &&      ) = default;
_ZN6nonstd13expected_lite6detail9storage_tIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2EOS9_:
  932|    168|        : storage_t_impl<T, E>( other.has_value() )
  933|    168|    {
  934|    168|        if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
  ------------------
  |  Branch (934:14): [True: 0, False: 168]
  ------------------
  935|    168|        else                     this->construct_error( std::move( other.error() ) );
  936|    168|    }
_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|    336|    {
  772|    336|        return m_error;
  773|    336|    }
_ZNR6nonstd13expected_lite15unexpected_typeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 1334|  1.54k|    {
 1335|  1.54k|        return m_error;
 1336|  1.54k|    }
_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|    168|    {
 2242|       |        return assert( ! has_value() ), contained.error();
 2243|    168|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|   536k|    {
 2038|   536k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 535k, False: 336]
  ------------------
 2039|    336|        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|    336|    {
  732|    336|        m_error.~error_type();
  733|    336|    }
_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|   208k|    : contained( true )
 1928|   208k|    {
 1929|   208k|        contained.construct_value( std::forward<U>( value ) );
 1930|   208k|    }
_ZN6nonstd13expected_lite6detail9storage_tIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|   208k|        : storage_t_impl<T, E>( has_value )
  922|   208k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|   208k|        : m_has_value( has_value )
  674|   208k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOl:
  687|   208k|    {
  688|   208k|        new( &m_value ) value_type( std::move( e ) );
  689|   208k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|   208k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|   626k|    {
  787|   626k|        return m_has_value;
  788|   626k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|   208k|    {
  742|   208k|        return m_value;
  743|   208k|    }
_ZNK6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|   208k|    {
 2192|   208k|        return has_value();
 2193|   208k|    }
_ZNK6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|   626k|    {
 2197|   626k|        return contained.has_value();
 2198|   626k|    }
_ZNR6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|   208k|    {
 2211|   208k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 208k, False: 0]
  ------------------
 2212|   208k|            ? ( contained.value() )
 2213|   208k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|   208k|    }
_ZN6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|   208k|    {
 2038|   208k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 208k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|   208k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|   208k|    {
  705|   208k|        m_value.~value_type();
  706|   208k|    }
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.39k|    {
 2038|  5.39k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 3.85k, False: 1.54k]
  ------------------
 2039|  1.54k|        else               contained.destruct_error();
 2040|  5.39k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  3.85k|    {
  705|  3.85k|        m_value.~value_type();
  706|  3.85k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  1.54k|    {
  732|  1.54k|        m_error.~error_type();
  733|  1.54k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.39k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  6.94k|    {
 2038|  6.94k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 3.85k, False: 3.08k]
  ------------------
 2039|  3.08k|        else               contained.destruct_error();
 2040|  6.94k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  3.85k|    {
  705|  3.85k|        m_value.~value_type();
  706|  3.85k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  3.08k|    {
  732|  3.08k|        m_error.~error_type();
  733|  3.08k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  6.94k|    ~storage_t_impl() {}
_ZNR6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  3.85k|    {
 2211|  3.85k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 3.85k, False: 0]
  ------------------
 2212|  3.85k|            ? ( contained.value() )
 2213|  3.85k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  3.85k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  3.85k|    {
  742|  3.85k|        return m_value;
  743|  3.85k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
  771|  1.54k|    {
  772|  1.54k|        return m_error;
  773|  1.54k|    }
_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.64k|    : contained( true )
 1928|  2.64k|    {
 1929|  2.64k|        contained.construct_value( std::forward<U>( value ) );
 1930|  2.64k|    }
_ZN6nonstd13expected_lite6detail9storage_tIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.18k|        : storage_t_impl<T, E>( has_value )
  922|  5.18k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.18k|        : m_has_value( has_value )
  674|  5.18k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOS4_:
  687|  2.64k|    {
  688|  2.64k|        new( &m_value ) value_type( std::move( e ) );
  689|  2.64k|    }
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS9_TnNSt9enable_ifIXaasr3std16is_constructibleIS9_OT_EE5valuesr3std14is_convertibleISE_S9_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISD_EE:
 1977|  1.54k|    : contained( false )
 1978|  1.54k|    {
 1979|  1.54k|        contained.construct_error( std::move( error.error() ) );
 1980|  1.54k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOSA_:
  714|  2.53k|    {
  715|  2.53k|        new( &m_error ) error_type( std::move( e ) );
  716|  2.53k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.18k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  5.18k|    {
  787|  5.18k|        return m_has_value;
  788|  5.18k|    }
_ZNK6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  5.18k|    {
 2197|  5.18k|        return contained.has_value();
 2198|  5.18k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOSB_:
 1566|  1.54k|{
 1567|  1.54k|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|  1.54k|}
_ZN6nonstd13expected_lite15unexpected_typeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IRS7_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS7_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISC_E4typeESt10in_place_tEE5valuentsr3std7is_sameISG_S8_EE5valueEiE4typeELi0EEEOSC_:
 1237|  1.54k|    : m_error( std::forward<E2>( error ) )
 1238|  1.54k|    {}
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.18k|    {
 2038|  5.18k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 2.64k, False: 2.53k]
  ------------------
 2039|  2.53k|        else               contained.destruct_error();
 2040|  5.18k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  2.64k|    {
  705|  2.64k|        m_value.~value_type();
  706|  2.64k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  2.53k|    {
  732|  2.53k|        m_error.~error_type();
  733|  2.53k|    }
_ZNK6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_E9has_valueEv:
 2196|   491k|    {
 2197|   491k|        return contained.has_value();
 2198|   491k|    }
_ZNK6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_EcvbEv:
 2191|   163k|    {
 2192|   163k|        return has_value();
 2193|   163k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E9has_valueEv:
  786|   491k|    {
  787|   491k|        return m_has_value;
  788|   491k|    }
_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|   163k|    : contained( true )
 1928|   163k|    {
 1929|   163k|        contained.construct_value( std::forward<U>( value ) );
 1930|   163k|    }
_ZN6nonstd13expected_lite6detail9storage_tINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_Lb1ELb1EEC2Eb:
  921|   163k|        : storage_t_impl<T, E>( has_value )
  922|   163k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_EC2Eb:
  673|   163k|        : m_has_value( has_value )
  674|   163k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E15construct_valueEOS8_:
  687|   163k|    {
  688|   163k|        new( &m_value ) value_type( std::move( e ) );
  689|   163k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_ED2Ev:
  670|   163k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite15make_unexpectedIPKcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS6_:
 1566|  5.53k|{
 1567|  5.53k|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|  5.53k|}
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEv:
  677|  3.85k|    {
  678|  3.85k|        new( &m_value ) value_type();
  679|  3.85k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOS9_:
  714|  1.54k|    {
  715|  1.54k|        new( &m_error ) error_type( std::move( e ) );
  716|  1.54k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E5valueEv:
  741|   163k|    {
  742|   163k|        return m_value;
  743|   163k|    }
_ZNR6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_E5valueEv:
 2210|   163k|    {
 2211|   163k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 163k, False: 0]
  ------------------
 2212|   163k|            ? ( contained.value() )
 2213|   163k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|   163k|    }
_ZN6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_ED2Ev:
 2037|   163k|    {
 2038|   163k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 163k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|   163k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E14destruct_valueEv:
  704|   163k|    {
  705|   163k|        m_value.~value_type();
  706|   163k|    }
_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|  19.4k|    : contained( true )
 1928|  19.4k|    {
 1929|  19.4k|        contained.construct_value( std::forward<U>( value ) );
 1930|  19.4k|    }
_ZN6nonstd13expected_lite6detail9storage_tIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  19.4k|        : storage_t_impl<T, E>( has_value )
  922|  19.4k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  19.4k|        : m_has_value( has_value )
  674|  19.4k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOS4_:
  687|  19.4k|    {
  688|  19.4k|        new( &m_value ) value_type( std::move( e ) );
  689|  19.4k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  19.4k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  58.2k|    {
  787|  58.2k|        return m_has_value;
  788|  58.2k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  19.4k|    {
  742|  19.4k|        return m_value;
  743|  19.4k|    }
_ZNK6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  19.4k|    {
 2192|  19.4k|        return has_value();
 2193|  19.4k|    }
_ZNK6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  58.2k|    {
 2197|  58.2k|        return contained.has_value();
 2198|  58.2k|    }
_ZNR6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  19.4k|    {
 2211|  19.4k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 19.4k, False: 0]
  ------------------
 2212|  19.4k|            ? ( contained.value() )
 2213|  19.4k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  19.4k|    }
_ZN6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  19.4k|    {
 2038|  19.4k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 19.4k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  19.4k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  19.4k|    {
  705|  19.4k|        m_value.~value_type();
  706|  19.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.57k|    : contained( true )
 1928|  4.57k|    {
 1929|  4.57k|        contained.construct_value( std::forward<U>( value ) );
 1930|  4.57k|    }
_ZN6nonstd13expected_lite6detail9storage_tIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  4.57k|        : storage_t_impl<T, E>( has_value )
  922|  4.57k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  4.57k|        : m_has_value( has_value )
  674|  4.57k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOb:
  687|  4.57k|    {
  688|  4.57k|        new( &m_value ) value_type( std::move( e ) );
  689|  4.57k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  4.57k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  13.7k|    {
  787|  13.7k|        return m_has_value;
  788|  13.7k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  4.57k|    {
  742|  4.57k|        return m_value;
  743|  4.57k|    }
_ZNK6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  4.57k|    {
 2192|  4.57k|        return has_value();
 2193|  4.57k|    }
_ZNK6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  13.7k|    {
 2197|  13.7k|        return contained.has_value();
 2198|  13.7k|    }
_ZNR6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  4.57k|    {
 2211|  4.57k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 4.57k, False: 0]
  ------------------
 2212|  4.57k|            ? ( contained.value() )
 2213|  4.57k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  4.57k|    }
_ZN6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  4.57k|    {
 2038|  4.57k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 4.57k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  4.57k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  4.57k|    {
  705|  4.57k|        m_value.~value_type();
  706|  4.57k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRA13_KcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS7_:
 1566|     93|{
 1567|     93|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|     93|}
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IRA13_S2_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS9_E4typeESt10in_place_tEE5valuentsr3std7is_sameISD_S4_EE5valueEiE4typeELi0EEEOS9_:
 1237|     93|    : m_error( std::forward<E2>( error ) )
 1238|     93|    {}
_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleISF_OT_EE5valuesr3std14is_convertibleISM_SF_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISL_EE:
 1977|  3.08k|    : contained( false )
 1978|  3.08k|    {
 1979|  3.08k|        contained.construct_error( std::move( error.error() ) );
 1980|  3.08k|    }
_ZN6nonstd13expected_lite6detail9storage_tISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  6.94k|        : storage_t_impl<T, E>( has_value )
  922|  6.94k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  6.94k|        : m_has_value( has_value )
  674|  6.94k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOSG_:
  714|  3.08k|    {
  715|  3.08k|        new( &m_error ) error_type( std::move( e ) );
  716|  3.08k|    }
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.85k|    : contained( true )
 1928|  3.85k|    {
 1929|  3.85k|        contained.construct_value( std::forward<U>( value ) );
 1930|  3.85k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOSA_:
  687|  3.85k|    {
  688|  3.85k|        new( &m_value ) value_type( std::move( e ) );
  689|  3.85k|    }
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IS3_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS7_E4typeESt10in_place_tEE5valuentsr3std7is_sameISB_S4_EE5valueEiE4typeELi0EEEOS7_:
 1237|  5.53k|    : m_error( std::forward<E2>( error ) )
 1238|  5.53k|    {}
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS9_OT_EE5valuesr3std14is_convertibleISG_S9_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISF_EE:
 1977|    996|    : contained( false )
 1978|    996|    {
 1979|    996|        contained.construct_error( std::move( error.error() ) );
 1980|    996|    }
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS8_OT_EE5valuesr3std14is_convertibleISF_S8_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISE_EE:
 1977|  1.54k|    : contained( false )
 1978|  1.54k|    {
 1979|  1.54k|        contained.construct_error( std::move( error.error() ) );
 1980|  1.54k|    }
_ZN6nonstd13expected_lite6detail9storage_tISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.39k|        : storage_t_impl<T, E>( has_value )
  922|  5.39k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.39k|        : m_has_value( has_value )
  674|  5.39k|    {}
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2ILb1ETnNSt9enable_ifIXT_EiE4typeELi0EEEv:
 1787|  3.85k|    : contained( true )
 1788|  3.85k|    {
 1789|  3.85k|        contained.construct_value();
 1790|  3.85k|    }
_ZNR6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 2241|  1.54k|    {
 2242|       |        return assert( ! has_value() ), contained.error();
 2243|  1.54k|    }

_ZN2BT21BehaviorTreeExceptionC2IJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEDpRKT_:
   33|  6.14k|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|  6.14k|  {}
_ZNK2BT21BehaviorTreeException4whatEv:
   37|  6.52k|  {
   38|  6.52k|    return message_.c_str();
   39|  6.52k|  }
_ZN2BT12RuntimeErrorC2IJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEDpRKT_:
   67|  6.14k|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|  6.14k|  {}
_ZN2BT12RuntimeErrorC2IJA42_cEEEDpRKT_:
   67|      2|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      2|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA42_cEEEDpRKT_:
   33|      2|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      2|  {}
_ZN2BT12RuntimeErrorC2IJA33_cEEEDpRKT_:
   67|    176|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|    176|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA33_cEEEDpRKT_:
   33|    176|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|    176|  {}
_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|     26|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|     26|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA47_cEEEDpRKT_:
   33|     26|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|     26|  {}
_ZN2BT12RuntimeErrorC2IJA63_cEEEDpRKT_:
   67|      8|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      8|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA63_cEEEDpRKT_:
   33|      8|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      8|  {}
_ZN2BT12RuntimeErrorC2IJA35_cEEEDpRKT_:
   67|      5|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      5|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA35_cEEEDpRKT_:
   33|      5|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      5|  {}
_ZN2BT12RuntimeErrorC2IJA74_cEEEDpRKT_:
   67|      9|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      9|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA74_cEEEDpRKT_:
   33|      9|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      9|  {}
_ZN2BT12RuntimeErrorC2IJA79_cEEEDpRKT_:
   67|    131|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|    131|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA79_cEEEDpRKT_:
   33|    131|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|    131|  {}
_ZN2BT12RuntimeErrorC2IJA24_cEEEDpRKT_:
   67|     23|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|     23|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA24_cEEEDpRKT_:
   33|     23|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|     23|  {}

_ZN2BT3Ast19ExprUnaryArithmeticC2ENS1_4op_tESt10shared_ptrINS0_8ExprBaseEE:
  118|  18.5k|  explicit ExprUnaryArithmetic(op_t op, expr_ptr e) : op(op), rhs(std::move(e))
  119|  18.5k|  {}
_ZN2BT3Ast8ExprBaseD2Ev:
   57|  5.98M|  virtual ~ExprBase() = default;
_ZNK2BT3Ast19ExprUnaryArithmetic8evaluateERNS0_11EnvironmentE:
  122|  4.82k|  {
  123|  4.82k|    auto rhs_v = rhs->evaluate(env);
  124|  4.82k|    if(rhs_v.isNumber())
  ------------------
  |  Branch (124:8): [True: 3.06k, False: 1.75k]
  ------------------
  125|  3.06k|    {
  126|  3.06k|      const double rv = rhs_v.cast<double>();
  127|  3.06k|      switch(op)
  ------------------
  |  Branch (127:14): [True: 3.05k, False: 11]
  ------------------
  128|  3.06k|      {
  129|    851|        case negate:
  ------------------
  |  Branch (129:9): [True: 851, False: 2.21k]
  ------------------
  130|    851|          return Any(-rv);
  131|    785|        case complement:
  ------------------
  |  Branch (131:9): [True: 785, False: 2.28k]
  ------------------
  132|    785|          if(rv > static_cast<double>(std::numeric_limits<int64_t>::max()) ||
  ------------------
  |  Branch (132:14): [True: 1, False: 784]
  ------------------
  133|    784|             rv < static_cast<double>(std::numeric_limits<int64_t>::min()))
  ------------------
  |  Branch (133:14): [True: 1, False: 783]
  ------------------
  134|      2|          {
  135|      2|            throw RuntimeError("Number out of range for bitwise operation");
  136|      2|          }
  137|    783|          return Any(static_cast<double>(~static_cast<int64_t>(rv)));
  138|  1.42k|        case logical_not:
  ------------------
  |  Branch (138:9): [True: 1.42k, False: 1.64k]
  ------------------
  139|  1.42k|          return Any(static_cast<double>(!static_cast<bool>(rv)));
  140|  3.06k|      }
  141|  3.06k|    }
  142|  1.75k|    else if(rhs_v.isString())
  ------------------
  |  Branch (142:13): [True: 1.73k, False: 22]
  ------------------
  143|  1.73k|    {
  144|  1.73k|      if(op == logical_not)
  ------------------
  |  Branch (144:10): [True: 1.73k, False: 2]
  ------------------
  145|  1.73k|      {
  146|  1.73k|        const auto str = rhs_v.cast<std::string>();
  147|  1.73k|        if(str == "true" || str == "True" || str == "TRUE" || str == "1")
  ------------------
  |  Branch (147:12): [True: 196, False: 1.53k]
  |  Branch (147:29): [True: 196, False: 1.34k]
  |  Branch (147:46): [True: 194, False: 1.14k]
  |  Branch (147:63): [True: 197, False: 950]
  ------------------
  148|    783|        {
  149|    783|          return Any(0.0);
  150|    783|        }
  151|    950|        if(str == "false" || str == "False" || str == "FALSE" || str == "0")
  ------------------
  |  Branch (151:12): [True: 194, False: 756]
  |  Branch (151:30): [True: 194, False: 562]
  |  Branch (151:48): [True: 194, False: 368]
  |  Branch (151:66): [True: 194, False: 174]
  ------------------
  152|    776|        {
  153|    776|          return Any(1.0);
  154|    776|        }
  155|    950|      }
  156|    176|      throw RuntimeError("Invalid operator for std::string");
  157|  1.73k|    }
  158|     22|    throw RuntimeError("ExprUnaryArithmetic: undefined");
  159|  4.82k|  }
_ZN2BT3Ast11ExprLiteralC2ENS_3AnyE:
   71|  1.50M|  ExprLiteral(Any v) : value(v)
   72|  1.50M|  {}
_ZNK2BT3Ast11ExprLiteral8evaluateERNS0_11EnvironmentE:
   75|   193k|  {
   76|   193k|    return value;
   77|   193k|  }
_ZN2BT3Ast8ExprNameC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   84|  4.01M|  explicit ExprName(std::string n) : name(std::move(n))
   85|  4.01M|  {}
_ZNK2BT3Ast8ExprName8evaluateERNS0_11EnvironmentE:
   88|  73.4k|  {
   89|       |    //search first in the enums table
   90|  73.4k|    if(env.enums)
  ------------------
  |  Branch (90:8): [True: 73.4k, False: 0]
  ------------------
   91|  73.4k|    {
   92|  73.4k|      auto enum_ptr = env.enums->find(name);
   93|  73.4k|      if(enum_ptr != env.enums->end())
  ------------------
  |  Branch (93:10): [True: 0, False: 73.4k]
  ------------------
   94|      0|      {
   95|      0|        return Any(double(enum_ptr->second));
   96|      0|      }
   97|  73.4k|    }
   98|       |    // search now in the variables table
   99|  73.4k|    auto any_ref = env.vars->getAnyLocked(name);
  100|  73.4k|    if(!any_ref)
  ------------------
  |  Branch (100:8): [True: 446, False: 73.0k]
  ------------------
  101|    446|    {
  102|    446|      throw RuntimeError(StrCat("Variable not found: ", name));
  103|    446|    }
  104|  73.0k|    return *any_ref.get();
  105|  73.4k|  }
_ZN2BT3Ast14ExprAssignmentC2ESt10shared_ptrINS0_8ExprBaseEENS1_4op_tES4_:
  519|  50.0k|    : op(op), lhs(std::move(_lhs)), rhs(std::move(_rhs))
  520|  50.0k|  {}
_ZNK2BT3Ast14ExprAssignment8evaluateERNS0_11EnvironmentE:
  523|  21.2k|  {
  524|  21.2k|    auto varname = dynamic_cast<ExprName*>(lhs.get());
  525|  21.2k|    if(!varname)
  ------------------
  |  Branch (525:8): [True: 26, False: 21.1k]
  ------------------
  526|     26|    {
  527|     26|      throw RuntimeError("Assignment left operand not a blackboard entry");
  528|     26|    }
  529|  21.1k|    const auto& key = varname->name;
  530|       |
  531|  21.1k|    auto entry = env.vars->getEntry(key);
  532|  21.1k|    if(!entry)
  ------------------
  |  Branch (532:8): [True: 8.39k, False: 12.7k]
  ------------------
  533|  8.39k|    {
  534|       |      // variable doesn't exist, create it if using operator assign_create
  535|  8.39k|      if(op == assign_create)
  ------------------
  |  Branch (535:10): [True: 8.34k, False: 43]
  ------------------
  536|  8.34k|      {
  537|  8.34k|        env.vars->createEntry(key, PortInfo());
  538|  8.34k|        entry = env.vars->getEntry(key);
  539|  8.34k|        if(!entry)
  ------------------
  |  Branch (539:12): [True: 0, False: 8.34k]
  ------------------
  540|      0|        {
  541|      0|          throw LogicError("Bug: report");
  542|      0|        }
  543|  8.34k|      }
  544|     43|      else
  545|     43|      {
  546|       |        // fail otherwise
  547|     43|        auto msg = StrCat("The blackboard entry [", key,
  548|     43|                          "] doesn't exist, yet.\n"
  549|     43|                          "If you want to create a new one, "
  550|     43|                          "use the operator "
  551|     43|                          "[:=] instead of [=]");
  552|     43|        throw RuntimeError(msg);
  553|     43|      }
  554|  8.39k|    }
  555|  21.1k|    auto value = rhs->evaluate(env);
  556|       |
  557|  21.1k|    std::scoped_lock lock(entry->entry_mutex);
  558|  21.1k|    auto* dst_ptr = &entry->value;
  559|       |
  560|  21.1k|    auto errorPrefix = [dst_ptr, &key]() {
  561|  21.1k|      return StrCat("Error assigning a value to entry [", key, "] with type [",
  562|  21.1k|                    BT::demangle(dst_ptr->type()), "]. ");
  563|  21.1k|    };
  564|       |
  565|  21.1k|    if(value.empty())
  ------------------
  |  Branch (565:8): [True: 43, False: 21.0k]
  ------------------
  566|     43|    {
  567|     43|      throw RuntimeError(ErrorNotInit("right", opStr()));
  568|     43|    }
  569|       |
  570|  21.0k|    if(op == assign_create || op == assign_existing)
  ------------------
  |  Branch (570:8): [True: 10.4k, False: 10.6k]
  |  Branch (570:31): [True: 2.08k, False: 8.59k]
  ------------------
  571|  9.56k|    {
  572|       |      // the very fist assignment can come from any type.
  573|       |      // In the future, type check will be done by Any::copyInto
  574|  9.56k|      if(dst_ptr->empty() && entry->info.type() == typeid(AnyTypeAllowed))
  ------------------
  |  Branch (574:10): [True: 6.92k, False: 2.63k]
  |  Branch (574:10): [True: 6.92k, False: 2.63k]
  |  Branch (574:30): [True: 6.92k, False: 0]
  ------------------
  575|  6.92k|      {
  576|  6.92k|        *dst_ptr = value;
  577|  6.92k|      }
  578|  2.63k|      else if(value.isString() && !dst_ptr->isString())
  ------------------
  |  Branch (578:15): [True: 1.49k, False: 1.14k]
  |  Branch (578:35): [True: 664, False: 832]
  ------------------
  579|    664|      {
  580|       |        // special case: string to other type.
  581|       |        // Check if we can use the StringConverter
  582|    664|        auto const str = value.cast<std::string>();
  583|    664|        const auto* entry_info = env.vars->entryInfo(key);
  584|       |
  585|    664|        if(auto converter = entry_info->converter())
  ------------------
  |  Branch (585:17): [True: 0, False: 664]
  ------------------
  586|      0|        {
  587|      0|          *dst_ptr = converter(str);
  588|      0|        }
  589|    664|        else if(dst_ptr->isNumber())
  ------------------
  |  Branch (589:17): [True: 664, False: 0]
  ------------------
  590|    664|        {
  591|    664|          auto num_value = StringToDouble(value, env);
  592|    664|          *dst_ptr = Any(num_value);
  593|    664|        }
  594|      0|        else
  595|      0|        {
  596|      0|          auto msg = StrCat(errorPrefix(),
  597|      0|                            "\nThe right operand is a string, "
  598|      0|                            "can't convert to ",
  599|      0|                            demangle(dst_ptr->type()));
  600|      0|          throw RuntimeError(msg);
  601|      0|        }
  602|    664|      }
  603|  1.97k|      else
  604|  1.97k|      {
  605|  1.97k|        try
  606|  1.97k|        {
  607|  1.97k|          value.copyInto(*dst_ptr);
  608|  1.97k|        }
  609|  1.97k|        catch(std::exception&)
  610|  1.97k|        {
  611|     56|          auto msg = StrCat(errorPrefix(), "\nThe right operand has type [",
  612|     56|                            BT::demangle(value.type()), "] and can't be converted to [",
  613|     56|                            BT::demangle(dst_ptr->type()), "]");
  614|     56|          throw RuntimeError(msg);
  615|     56|        }
  616|  1.97k|      }
  617|  9.50k|      entry->sequence_id++;
  618|  9.50k|      entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  619|  9.50k|      return *dst_ptr;
  620|  9.56k|    }
  621|       |
  622|  11.5k|    if(dst_ptr->empty())
  ------------------
  |  Branch (622:8): [True: 5, False: 11.5k]
  ------------------
  623|      5|    {
  624|      5|      throw RuntimeError(ErrorNotInit("left", opStr()));
  625|      5|    }
  626|       |
  627|       |    // temporary use
  628|  11.5k|    Any temp_variable = *dst_ptr;
  629|       |
  630|  11.5k|    if(value.isNumber())
  ------------------
  |  Branch (630:8): [True: 1.85k, False: 9.67k]
  ------------------
  631|  1.85k|    {
  632|  1.85k|      if(!temp_variable.isNumber())
  ------------------
  |  Branch (632:10): [True: 8, False: 1.84k]
  ------------------
  633|      8|      {
  634|      8|        throw RuntimeError("This Assignment operator can't be used "
  635|      8|                           "with a non-numeric type");
  636|      8|      }
  637|       |
  638|  1.84k|      auto lv = temp_variable.cast<double>();
  639|  1.84k|      auto rv = value.cast<double>();
  640|  1.84k|      switch(op)
  641|  1.84k|      {
  642|    469|        case assign_plus:
  ------------------
  |  Branch (642:9): [True: 469, False: 1.37k]
  ------------------
  643|    469|          temp_variable = Any(lv + rv);
  644|    469|          break;
  645|    457|        case assign_minus:
  ------------------
  |  Branch (645:9): [True: 457, False: 1.38k]
  ------------------
  646|    457|          temp_variable = Any(lv - rv);
  647|    457|          break;
  648|    517|        case assign_times:
  ------------------
  |  Branch (648:9): [True: 517, False: 1.32k]
  ------------------
  649|    517|          temp_variable = Any(lv * rv);
  650|    517|          break;
  651|    397|        case assign_div:
  ------------------
  |  Branch (651:9): [True: 397, False: 1.44k]
  ------------------
  652|    397|          temp_variable = Any(lv / rv);
  653|    397|          break;
  654|      0|        default: {
  ------------------
  |  Branch (654:9): [True: 0, False: 1.84k]
  ------------------
  655|      0|        }
  656|  1.84k|      }
  657|  1.84k|    }
  658|  9.67k|    else if(value.isString())
  ------------------
  |  Branch (658:13): [True: 6.74k, False: 2.93k]
  ------------------
  659|  6.74k|    {
  660|  6.74k|      if(op == assign_plus)
  ------------------
  |  Branch (660:10): [True: 6.73k, False: 5]
  ------------------
  661|  6.73k|      {
  662|  6.73k|        auto lv = temp_variable.cast<std::string>();
  663|  6.73k|        auto rv = value.cast<std::string>();
  664|  6.73k|        temp_variable = Any(lv + rv);
  665|  6.73k|      }
  666|      5|      else
  667|      5|      {
  668|      5|        throw RuntimeError("Operator not supported for strings");
  669|      5|      }
  670|  6.74k|    }
  671|       |
  672|  11.5k|    temp_variable.copyInto(*dst_ptr);
  673|  11.5k|    entry->sequence_id++;
  674|  11.5k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  675|  11.5k|    return *dst_ptr;
  676|  11.5k|  }
_ZN2BT3Ast12ErrorNotInitB5cxx11EPKcS2_:
   62|     70|{
   63|     70|  return StrCat("The ", side, " operand of the operator [", op_str,
   64|     70|                "] is not initialized");
   65|     70|}
_ZNK2BT3Ast14ExprAssignment5opStrEv:
  497|     48|  {
  498|     48|    switch(op)
  ------------------
  |  Branch (498:12): [True: 48, False: 0]
  ------------------
  499|     48|    {
  500|     23|      case assign_create:
  ------------------
  |  Branch (500:7): [True: 23, False: 25]
  ------------------
  501|     23|        return ":=";
  502|     17|      case assign_existing:
  ------------------
  |  Branch (502:7): [True: 17, False: 31]
  ------------------
  503|     17|        return "=";
  504|      2|      case assign_plus:
  ------------------
  |  Branch (504:7): [True: 2, False: 46]
  ------------------
  505|      2|        return "+=";
  506|      2|      case assign_minus:
  ------------------
  |  Branch (506:7): [True: 2, False: 46]
  ------------------
  507|      2|        return "-=";
  508|      2|      case assign_times:
  ------------------
  |  Branch (508:7): [True: 2, False: 46]
  ------------------
  509|      2|        return "*=";
  510|      2|      case assign_div:
  ------------------
  |  Branch (510:7): [True: 2, False: 46]
  ------------------
  511|      2|        return "/=";
  512|     48|    }
  513|      0|    return "";
  514|     48|  }
_ZN2BT3Ast14StringToDoubleERKNS_3AnyERKNS0_11EnvironmentE:
   32|  49.7k|{
   33|  49.7k|  const auto str = value.cast<std::string>();
   34|  49.7k|  if(str == "true")
  ------------------
  |  Branch (34:6): [True: 194, False: 49.5k]
  ------------------
   35|    194|  {
   36|    194|    return 1.0;
   37|    194|  }
   38|  49.5k|  if(str == "false")
  ------------------
  |  Branch (38:6): [True: 195, False: 49.3k]
  ------------------
   39|    195|  {
   40|    195|    return 0.0;
   41|    195|  }
   42|  49.3k|  if(env.enums)
  ------------------
  |  Branch (42:6): [True: 49.3k, False: 0]
  ------------------
   43|  49.3k|  {
   44|  49.3k|    auto it = env.enums->find(str);
   45|  49.3k|    if(it != env.enums->end())
  ------------------
  |  Branch (45:8): [True: 0, False: 49.3k]
  ------------------
   46|      0|    {
   47|      0|      return it->second;
   48|      0|    }
   49|  49.3k|  }
   50|  49.3k|  return value.cast<double>();
   51|  49.3k|}
_ZZNK2BT3Ast14ExprAssignment8evaluateERNS0_11EnvironmentEENKUlvE_clB5cxx11Ev:
  560|     56|    auto errorPrefix = [dst_ptr, &key]() {
  561|     56|      return StrCat("Error assigning a value to entry [", key, "] with type [",
  562|     56|                    BT::demangle(dst_ptr->type()), "]. ");
  563|     56|    };
_ZN2BT3Ast6ExprIfC2ESt10shared_ptrINS0_8ExprBaseEES4_S4_:
  465|  3.97k|    : condition(std::move(condition)), then(std::move(then)), else_(std::move(else_))
  466|  3.97k|  {}
_ZNK2BT3Ast6ExprIf8evaluateERNS0_11EnvironmentE:
  469|    941|  {
  470|    941|    const auto& v = condition->evaluate(env);
  471|    941|    bool valid = (v.isType<SimpleString>() && v.cast<SimpleString>().size() > 0) ||
  ------------------
  |  Branch (471:19): [True: 0, False: 941]
  |  Branch (471:47): [True: 0, False: 0]
  ------------------
  472|    934|                 (v.cast<double>() != 0.0);
  ------------------
  |  Branch (472:18): [True: 573, False: 361]
  ------------------
  473|    941|    if(valid)
  ------------------
  |  Branch (473:8): [True: 570, False: 371]
  ------------------
  474|    570|    {
  475|    570|      return then->evaluate(env);
  476|    570|    }
  477|    371|    else
  478|    371|    {
  479|    371|      return else_->evaluate(env);
  480|    371|    }
  481|    941|  }
_ZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentE:
  364|  14.2k|  {
  365|  14.2k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  366|  14.2k|      switch(op)
  367|  14.2k|      {
  368|  14.2k|        case equal:
  369|  14.2k|          if(!IsSame(lv, rv))
  370|  14.2k|            return false;
  371|  14.2k|          break;
  372|  14.2k|        case not_equal:
  373|  14.2k|          if(IsSame(lv, rv))
  374|  14.2k|            return false;
  375|  14.2k|          break;
  376|  14.2k|        case less:
  377|  14.2k|          if(lv >= rv)
  378|  14.2k|            return false;
  379|  14.2k|          break;
  380|  14.2k|        case greater:
  381|  14.2k|          if(lv <= rv)
  382|  14.2k|            return false;
  383|  14.2k|          break;
  384|  14.2k|        case less_equal:
  385|  14.2k|          if(lv > rv)
  386|  14.2k|            return false;
  387|  14.2k|          break;
  388|  14.2k|        case greater_equal:
  389|  14.2k|          if(lv < rv)
  390|  14.2k|            return false;
  391|  14.2k|          break;
  392|  14.2k|      }
  393|  14.2k|      return true;
  394|  14.2k|    };
  395|       |
  396|  14.2k|    auto lhs_v = operands[0]->evaluate(env);
  397|  93.2k|    for(auto i = 0u; i != ops.size(); ++i)
  ------------------
  |  Branch (397:22): [True: 87.2k, False: 6.02k]
  ------------------
  398|  87.2k|    {
  399|  87.2k|      auto rhs_v = operands[i + 1]->evaluate(env);
  400|       |
  401|  87.2k|      if(lhs_v.empty())
  ------------------
  |  Branch (401:10): [True: 10, False: 87.1k]
  ------------------
  402|     10|      {
  403|     10|        throw RuntimeError(ErrorNotInit("left", opStr(ops[i])));
  404|     10|      }
  405|  87.1k|      if(rhs_v.empty())
  ------------------
  |  Branch (405:10): [True: 2, False: 87.1k]
  ------------------
  406|      2|      {
  407|      2|        throw RuntimeError(ErrorNotInit("right", opStr(ops[i])));
  408|      2|      }
  409|  87.1k|      const Any False(0.0);
  410|       |
  411|  87.1k|      if(lhs_v.isNumber() && rhs_v.isNumber())
  ------------------
  |  Branch (411:10): [True: 52.5k, False: 34.6k]
  |  Branch (411:30): [True: 28.1k, False: 24.3k]
  ------------------
  412|  28.1k|      {
  413|  28.1k|        auto lv = lhs_v.cast<double>();
  414|  28.1k|        auto rv = rhs_v.cast<double>();
  415|  28.1k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (415:12): [True: 1.18k, False: 27.0k]
  ------------------
  416|  1.18k|        {
  417|  1.18k|          return False;
  418|  1.18k|        }
  419|  28.1k|      }
  420|  58.9k|      else if(lhs_v.isString() && rhs_v.isString())
  ------------------
  |  Branch (420:15): [True: 34.4k, False: 24.5k]
  |  Branch (420:35): [True: 9.70k, False: 24.7k]
  ------------------
  421|  9.70k|      {
  422|  9.70k|        auto lv = lhs_v.cast<SimpleString>();
  423|  9.70k|        auto rv = rhs_v.cast<SimpleString>();
  424|  9.70k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (424:12): [True: 4.03k, False: 5.67k]
  ------------------
  425|  4.03k|        {
  426|  4.03k|          return False;
  427|  4.03k|        }
  428|  9.70k|      }
  429|  49.2k|      else if(lhs_v.isString() && rhs_v.isNumber())
  ------------------
  |  Branch (429:15): [True: 24.7k, False: 24.5k]
  |  Branch (429:35): [True: 24.7k, False: 0]
  ------------------
  430|  24.7k|      {
  431|  24.7k|        auto lv = StringToDouble(lhs_v, env);
  432|  24.7k|        auto rv = rhs_v.cast<double>();
  433|  24.7k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (433:12): [True: 1.40k, False: 23.3k]
  ------------------
  434|  1.40k|        {
  435|  1.40k|          return False;
  436|  1.40k|        }
  437|  24.7k|      }
  438|  24.5k|      else if(lhs_v.isNumber() && rhs_v.isString())
  ------------------
  |  Branch (438:15): [True: 24.3k, False: 199]
  |  Branch (438:35): [True: 24.3k, False: 0]
  ------------------
  439|  24.3k|      {
  440|  24.3k|        auto lv = lhs_v.cast<double>();
  441|  24.3k|        auto rv = StringToDouble(rhs_v, env);
  442|  24.3k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (442:12): [True: 1.35k, False: 23.0k]
  ------------------
  443|  1.35k|        {
  444|  1.35k|          return False;
  445|  1.35k|        }
  446|  24.3k|      }
  447|    199|      else
  448|    199|      {
  449|    199|        throw RuntimeError(StrCat("Can't mix different types in Comparison. "
  450|    199|                                  "Left operand [",
  451|    199|                                  BT::demangle(lhs_v.type()), "] right operand [",
  452|    199|                                  BT::demangle(rhs_v.type()), "]"));
  453|    199|      }
  454|  79.0k|      lhs_v = rhs_v;
  455|  79.0k|    }
  456|  6.02k|    return Any(1.0);
  457|  14.2k|  }
_ZNK2BT3Ast14ExprComparison5opStrENS1_4op_tE:
  341|     12|  {
  342|     12|    switch(op)
  ------------------
  |  Branch (342:12): [True: 12, False: 0]
  ------------------
  343|     12|    {
  344|      0|      case equal:
  ------------------
  |  Branch (344:7): [True: 0, False: 12]
  ------------------
  345|      0|        return "==";
  346|      1|      case not_equal:
  ------------------
  |  Branch (346:7): [True: 1, False: 11]
  ------------------
  347|      1|        return "!=";
  348|      3|      case less:
  ------------------
  |  Branch (348:7): [True: 3, False: 9]
  ------------------
  349|      3|        return "<";
  350|      7|      case greater:
  ------------------
  |  Branch (350:7): [True: 7, False: 5]
  ------------------
  351|      7|        return ">";
  352|      0|      case less_equal:
  ------------------
  |  Branch (352:7): [True: 0, False: 12]
  ------------------
  353|      0|        return "<=";
  354|      1|      case greater_equal:
  ------------------
  |  Branch (354:7): [True: 1, False: 11]
  ------------------
  355|      1|        return ">=";
  356|     12|    }
  357|      0|    return "";
  358|     12|  }
_ZZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentEENKUlRKT_RKT0_NS1_4op_tEE_clIddEEDaS6_S9_SA_:
  365|  77.1k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  366|  77.1k|      switch(op)
  ------------------
  |  Branch (366:14): [True: 77.1k, False: 0]
  ------------------
  367|  77.1k|      {
  368|  1.45k|        case equal:
  ------------------
  |  Branch (368:9): [True: 1.45k, False: 75.6k]
  ------------------
  369|  1.45k|          if(!IsSame(lv, rv))
  ------------------
  |  Branch (369:14): [True: 719, False: 735]
  ------------------
  370|    719|            return false;
  371|    735|          break;
  372|  18.0k|        case not_equal:
  ------------------
  |  Branch (372:9): [True: 18.0k, False: 59.0k]
  ------------------
  373|  18.0k|          if(IsSame(lv, rv))
  ------------------
  |  Branch (373:14): [True: 583, False: 17.5k]
  ------------------
  374|    583|            return false;
  375|  17.5k|          break;
  376|  27.6k|        case less:
  ------------------
  |  Branch (376:9): [True: 27.6k, False: 49.5k]
  ------------------
  377|  27.6k|          if(lv >= rv)
  ------------------
  |  Branch (377:14): [True: 699, False: 26.9k]
  ------------------
  378|    699|            return false;
  379|  26.9k|          break;
  380|  27.1k|        case greater:
  ------------------
  |  Branch (380:9): [True: 27.1k, False: 50.0k]
  ------------------
  381|  27.1k|          if(lv <= rv)
  ------------------
  |  Branch (381:14): [True: 728, False: 26.4k]
  ------------------
  382|    728|            return false;
  383|  26.4k|          break;
  384|  26.4k|        case less_equal:
  ------------------
  |  Branch (384:9): [True: 1.20k, False: 75.9k]
  ------------------
  385|  1.20k|          if(lv > rv)
  ------------------
  |  Branch (385:14): [True: 586, False: 616]
  ------------------
  386|    586|            return false;
  387|    616|          break;
  388|  1.62k|        case greater_equal:
  ------------------
  |  Branch (388:9): [True: 1.62k, False: 75.5k]
  ------------------
  389|  1.62k|          if(lv < rv)
  ------------------
  |  Branch (389:14): [True: 627, False: 995]
  ------------------
  390|    627|            return false;
  391|    995|          break;
  392|  77.1k|      }
  393|  73.1k|      return true;
  394|  77.1k|    };
_ZN2BT3Ast6IsSameIdEEbRKT_S4_:
  316|  19.5k|{
  317|       |  if constexpr(std::is_same_v<double, T>)
  318|  19.5k|  {
  319|  19.5k|    constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
  320|  19.5k|    return std::abs(lv - rv) <= EPS;
  321|       |  }
  322|       |  else
  323|       |  {
  324|       |    return (lv == rv);
  325|       |  }
  326|  19.5k|}
_ZZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentEENKUlRKT_RKT0_NS1_4op_tEE_clIN7SafeAny12SimpleStringESE_EEDaS6_S9_SA_:
  365|  9.70k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  366|  9.70k|      switch(op)
  ------------------
  |  Branch (366:14): [True: 9.70k, False: 0]
  ------------------
  367|  9.70k|      {
  368|    906|        case equal:
  ------------------
  |  Branch (368:9): [True: 906, False: 8.80k]
  ------------------
  369|    906|          if(!IsSame(lv, rv))
  ------------------
  |  Branch (369:14): [True: 518, False: 388]
  ------------------
  370|    518|            return false;
  371|    388|          break;
  372|  1.22k|        case not_equal:
  ------------------
  |  Branch (372:9): [True: 1.22k, False: 8.48k]
  ------------------
  373|  1.22k|          if(IsSame(lv, rv))
  ------------------
  |  Branch (373:14): [True: 411, False: 813]
  ------------------
  374|    411|            return false;
  375|    813|          break;
  376|  1.46k|        case less:
  ------------------
  |  Branch (376:9): [True: 1.46k, False: 8.24k]
  ------------------
  377|  1.46k|          if(lv >= rv)
  ------------------
  |  Branch (377:14): [True: 939, False: 524]
  ------------------
  378|    939|            return false;
  379|    524|          break;
  380|  2.33k|        case greater:
  ------------------
  |  Branch (380:9): [True: 2.33k, False: 7.37k]
  ------------------
  381|  2.33k|          if(lv <= rv)
  ------------------
  |  Branch (381:14): [True: 1.13k, False: 1.20k]
  ------------------
  382|  1.13k|            return false;
  383|  1.20k|          break;
  384|  1.22k|        case less_equal:
  ------------------
  |  Branch (384:9): [True: 1.22k, False: 8.48k]
  ------------------
  385|  1.22k|          if(lv > rv)
  ------------------
  |  Branch (385:14): [True: 470, False: 750]
  ------------------
  386|    470|            return false;
  387|    750|          break;
  388|  2.56k|        case greater_equal:
  ------------------
  |  Branch (388:9): [True: 2.56k, False: 7.14k]
  ------------------
  389|  2.56k|          if(lv < rv)
  ------------------
  |  Branch (389:14): [True: 567, False: 1.99k]
  ------------------
  390|    567|            return false;
  391|  1.99k|          break;
  392|  9.70k|      }
  393|  5.67k|      return true;
  394|  9.70k|    };
_ZN2BT3Ast6IsSameIN7SafeAny12SimpleStringEEEbRKT_S6_:
  316|  2.13k|{
  317|       |  if constexpr(std::is_same_v<double, T>)
  318|       |  {
  319|       |    constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
  320|       |    return std::abs(lv - rv) <= EPS;
  321|       |  }
  322|       |  else
  323|  2.13k|  {
  324|  2.13k|    return (lv == rv);
  325|  2.13k|  }
  326|  2.13k|}
_ZN2BT3Ast20ExprBinaryArithmeticC2ESt10shared_ptrINS0_8ExprBaseEENS1_4op_tES4_:
  211|   336k|    : op(op), lhs(std::move(lhs)), rhs(std::move(rhs))
  212|   336k|  {}
_ZNK2BT3Ast20ExprBinaryArithmetic8evaluateERNS0_11EnvironmentE:
  215|   155k|  {
  216|   155k|    auto lhs_v = lhs->evaluate(env);
  217|   155k|    auto rhs_v = rhs->evaluate(env);
  218|       |
  219|   155k|    if(lhs_v.empty())
  ------------------
  |  Branch (219:8): [True: 9, False: 155k]
  ------------------
  220|      9|    {
  221|      9|      throw RuntimeError(ErrorNotInit("left", opStr()));
  222|      9|    }
  223|   155k|    if(rhs_v.empty())
  ------------------
  |  Branch (223:8): [True: 1, False: 155k]
  ------------------
  224|      1|    {
  225|      1|      throw RuntimeError(ErrorNotInit("right", opStr()));
  226|      1|    }
  227|       |
  228|   155k|    if(rhs_v.isNumber() && lhs_v.isNumber())
  ------------------
  |  Branch (228:8): [True: 73.1k, False: 82.6k]
  |  Branch (228:28): [True: 71.6k, False: 1.43k]
  ------------------
  229|  71.6k|    {
  230|  71.6k|      auto lv = lhs_v.cast<double>();
  231|  71.6k|      auto rv = rhs_v.cast<double>();
  232|       |
  233|  71.6k|      switch(op)
  234|  71.6k|      {
  235|    377|        case plus:
  ------------------
  |  Branch (235:9): [True: 377, False: 71.3k]
  ------------------
  236|    377|          return Any(lv + rv);
  237|    337|        case minus:
  ------------------
  |  Branch (237:9): [True: 337, False: 71.3k]
  ------------------
  238|    337|          return Any(lv - rv);
  239|    275|        case times:
  ------------------
  |  Branch (239:9): [True: 275, False: 71.4k]
  ------------------
  240|    275|          return Any(lv * rv);
  241|    224|        case div:
  ------------------
  |  Branch (241:9): [True: 224, False: 71.4k]
  ------------------
  242|    224|          return Any(lv / rv);
  243|  70.4k|        default: {
  ------------------
  |  Branch (243:9): [True: 70.4k, False: 1.21k]
  ------------------
  244|  70.4k|        }
  245|  71.6k|      }
  246|       |
  247|  70.4k|      if(op == bit_and || op == bit_or || op == bit_xor)
  ------------------
  |  Branch (247:10): [True: 350, False: 70.1k]
  |  Branch (247:27): [True: 68.3k, False: 1.76k]
  |  Branch (247:43): [True: 282, False: 1.48k]
  ------------------
  248|  69.0k|      {
  249|  69.0k|        try
  250|  69.0k|        {
  251|  69.0k|          int64_t li = lhs_v.cast<int64_t>();
  252|  69.0k|          int64_t ri = rhs_v.cast<int64_t>();
  253|  69.0k|          switch(op)
  254|  69.0k|          {
  255|    345|            case bit_and:
  ------------------
  |  Branch (255:13): [True: 345, False: 68.6k]
  ------------------
  256|    345|              return Any(static_cast<double>(li & ri));
  257|  68.3k|            case bit_or:
  ------------------
  |  Branch (257:13): [True: 68.3k, False: 635]
  ------------------
  258|  68.3k|              return Any(static_cast<double>(li | ri));
  259|    281|            case bit_xor:
  ------------------
  |  Branch (259:13): [True: 281, False: 68.7k]
  ------------------
  260|    281|              return Any(static_cast<double>(li ^ ri));
  261|      0|            default: {
  ------------------
  |  Branch (261:13): [True: 0, False: 69.0k]
  ------------------
  262|      0|            }
  263|  69.0k|          }
  264|  69.0k|        }
  265|  69.0k|        catch(...)
  266|  69.0k|        {
  267|      9|          throw RuntimeError("Binary operators are not allowed if "
  268|      9|                             "one of the operands is not an integer");
  269|      9|        }
  270|  69.0k|      }
  271|       |
  272|  1.48k|      if(op == logic_or || op == logic_and)
  ------------------
  |  Branch (272:10): [True: 673, False: 807]
  |  Branch (272:28): [True: 591, False: 216]
  ------------------
  273|  1.26k|      {
  274|  1.26k|        try
  275|  1.26k|        {
  276|  1.26k|          auto lb = lhs_v.cast<bool>();
  277|  1.26k|          auto rb = rhs_v.cast<bool>();
  278|  1.26k|          switch(op)
  279|  1.26k|          {
  280|    630|            case logic_or:
  ------------------
  |  Branch (280:13): [True: 630, False: 634]
  ------------------
  281|    630|              return Any(static_cast<double>(lb || rb));
  ------------------
  |  Branch (281:46): [True: 244, False: 386]
  |  Branch (281:52): [True: 2, False: 384]
  ------------------
  282|    503|            case logic_and:
  ------------------
  |  Branch (282:13): [True: 503, False: 761]
  ------------------
  283|    503|              return Any(static_cast<double>(lb && rb));
  ------------------
  |  Branch (283:46): [True: 291, False: 212]
  |  Branch (283:52): [True: 286, False: 5]
  ------------------
  284|      0|            default: {
  ------------------
  |  Branch (284:13): [True: 0, False: 1.26k]
  ------------------
  285|      0|            }
  286|  1.26k|          }
  287|  1.26k|        }
  288|  1.26k|        catch(...)
  289|  1.26k|        {
  290|    131|          throw RuntimeError("Logic operators are not allowed if "
  291|    131|                             "one of the operands is not castable to bool");
  292|    131|        }
  293|  1.26k|      }
  294|  1.48k|    }
  295|  84.1k|    else if(rhs_v.isString() && lhs_v.isString() && op == plus)
  ------------------
  |  Branch (295:13): [True: 6.69k, False: 77.4k]
  |  Branch (295:33): [True: 4.75k, False: 1.94k]
  |  Branch (295:53): [True: 4.46k, False: 283]
  ------------------
  296|  4.46k|    {
  297|  4.46k|      return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
  298|  4.46k|    }
  299|  79.6k|    else if(op == concat && ((rhs_v.isString() && lhs_v.isString()) ||
  ------------------
  |  Branch (299:13): [True: 3.63k, False: 76.0k]
  |  Branch (299:31): [True: 2.21k, False: 1.42k]
  |  Branch (299:51): [True: 275, False: 1.93k]
  ------------------
  300|  3.36k|                             (rhs_v.isString() && lhs_v.isNumber()) ||
  ------------------
  |  Branch (300:31): [True: 1.93k, False: 1.42k]
  |  Branch (300:51): [True: 1.93k, False: 0]
  ------------------
  301|  1.42k|                             (rhs_v.isNumber() && lhs_v.isString())))
  ------------------
  |  Branch (301:31): [True: 1.42k, False: 0]
  |  Branch (301:51): [True: 1.42k, False: 0]
  ------------------
  302|  3.63k|    {
  303|  3.63k|      return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
  304|  3.63k|    }
  305|  76.0k|    else
  306|  76.0k|    {
  307|  76.0k|      throw RuntimeError("Operation not permitted");
  308|  76.0k|    }
  309|       |
  310|    216|    return {};  // unreachable
  311|   155k|  }
_ZNK2BT3Ast20ExprBinaryArithmetic5opStrEv:
  181|     10|  {
  182|     10|    switch(op)
  ------------------
  |  Branch (182:12): [True: 10, False: 0]
  ------------------
  183|     10|    {
  184|      1|      case plus:
  ------------------
  |  Branch (184:7): [True: 1, False: 9]
  ------------------
  185|      1|        return "+";
  186|      1|      case minus:
  ------------------
  |  Branch (186:7): [True: 1, False: 9]
  ------------------
  187|      1|        return "-";
  188|      2|      case times:
  ------------------
  |  Branch (188:7): [True: 2, False: 8]
  ------------------
  189|      2|        return "*";
  190|      2|      case div:
  ------------------
  |  Branch (190:7): [True: 2, False: 8]
  ------------------
  191|      2|        return "/";
  192|      0|      case concat:
  ------------------
  |  Branch (192:7): [True: 0, False: 10]
  ------------------
  193|      0|        return "..";
  194|      2|      case bit_and:
  ------------------
  |  Branch (194:7): [True: 2, False: 8]
  ------------------
  195|      2|        return "&";
  196|      0|      case bit_or:
  ------------------
  |  Branch (196:7): [True: 0, False: 10]
  ------------------
  197|      0|        return "|";
  198|      1|      case bit_xor:
  ------------------
  |  Branch (198:7): [True: 1, False: 9]
  ------------------
  199|      1|        return "^";
  200|      0|      case logic_and:
  ------------------
  |  Branch (200:7): [True: 0, False: 10]
  ------------------
  201|      0|        return "&&";
  202|      1|      case logic_or:
  ------------------
  |  Branch (202:7): [True: 1, False: 9]
  ------------------
  203|      1|        return "||";
  204|     10|    }
  205|      0|    return "";
  206|     10|  }

_ZN7SafeAny7details13convertNumberIldEEvRKT_RT0_:
  152|   180k|{
  153|   180k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|   180k|                                                                          "convertible");
  155|       |
  156|   180k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [True: 0, Folded]
  |  Branch (156:55): [Folded, False: 0]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|       |  {
  160|       |    if(source < 0)
  161|       |    {
  162|       |      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|       |    }
  164|       |  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|       |  {
  172|       |    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|       |  {
  177|       |    checkLowerLimit<SRC, DST>(source);
  178|       |    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|   180k|  {
  201|   180k|    bool both_float =
  202|   180k|        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  ------------------
  |  Branch (202:9): [Folded, False: 180k]
  |  Branch (202:47): [True: 0, Folded]
  ------------------
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|   180k|    if(!both_float)
  ------------------
  |  Branch (204:8): [True: 180k, False: 0]
  ------------------
  205|   180k|    {
  206|   180k|      checkTruncation<SRC, DST>(source);
  207|   180k|    }
  208|   180k|    target = static_cast<DST>(source);
  209|   180k|  }
  210|   180k|}
_ZN7SafeAny7details15checkTruncationIldEEvRKT_:
   92|   180k|{
   93|       |  // Handle integer to floating point
   94|       |  if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>)
   95|   180k|  {
   96|       |    // Check if value can be represented exactly in the target type
   97|   180k|    constexpr uint64_t max_exact = (1LL << std::numeric_limits<double>::digits) - 1;
   98|   180k|    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|   180k|    {
  105|   180k|      doesnt_fit = std::abs(static_cast<int64_t>(from)) > static_cast<int64_t>(max_exact);
  106|   180k|    }
  107|   180k|    if(doesnt_fit)
  ------------------
  |  Branch (107:8): [True: 20, False: 180k]
  ------------------
  108|     20|    {
  109|     20|      throw std::runtime_error("Loss of precision when converting a large integer number "
  110|     20|                               "to floating point:" +
  111|     20|                               std::to_string(from));
  112|     20|    }
  113|       |  }
  114|       |  // Handle floating point to integer
  115|       |  else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>)
  116|       |  {
  117|       |    // static_cast<From>(To::max) rounds up to an out-of-range value when To has
  118|       |    // more significant bits than From's mantissa (e.g. double -> int64_t). In
  119|       |    // that case a plain `>` lets the rounded boundary through and the cast to To
  120|       |    // below overflows, so use a half-open upper bound to reject it first.
  121|       |    constexpr bool max_rounds_up =
  122|       |        std::numeric_limits<To>::digits > std::numeric_limits<From>::digits;
  123|       |    const From max_limit = static_cast<From>(std::numeric_limits<To>::max());
  124|       |    const bool over = max_rounds_up ? (from >= max_limit) : (from > max_limit);
  125|       |    if(over || from < static_cast<From>(std::numeric_limits<To>::lowest()) ||
  126|       |       from != std::nearbyint(from))
  127|       |    {
  128|       |      throw std::runtime_error("Invalid floating point to integer conversion");
  129|       |    }
  130|       |  }
  131|       |  // Handle other conversions
  132|       |  else
  133|       |  {
  134|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  135|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()))
  136|       |    {
  137|       |      throw std::runtime_error("Value outside numeric limits");
  138|       |    }
  139|       |    To as_target = static_cast<To>(from);
  140|       |    From back_to_source = static_cast<From>(as_target);
  141|       |    if(from != back_to_source)
  142|       |    {
  143|       |      throw std::runtime_error("Value truncated in conversion");
  144|       |    }
  145|       |  }
  146|   180k|}
_ZN7SafeAny7details13convertNumberIdlEEvRKT_RT0_:
  152|  69.9k|{
  153|  69.9k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|  69.9k|                                                                          "convertible");
  155|       |
  156|  69.9k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [Folded, False: 69.9k]
  |  Branch (156:55): [True: 0, Folded]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|       |  {
  160|       |    if(source < 0)
  161|       |    {
  162|       |      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|       |    }
  164|       |  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|       |  {
  172|       |    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|       |  {
  177|       |    checkLowerLimit<SRC, DST>(source);
  178|       |    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|  69.9k|  {
  201|  69.9k|    bool both_float =
  202|  69.9k|        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  ------------------
  |  Branch (202:9): [True: 69.9k, Folded]
  |  Branch (202:47): [Folded, False: 69.9k]
  ------------------
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|  69.9k|    if(!both_float)
  ------------------
  |  Branch (204:8): [True: 69.9k, False: 0]
  ------------------
  205|  69.9k|    {
  206|  69.9k|      checkTruncation<SRC, DST>(source);
  207|  69.9k|    }
  208|  69.9k|    target = static_cast<DST>(source);
  209|  69.9k|  }
  210|  69.9k|}
_ZN7SafeAny7details15checkTruncationIdlEEvRKT_:
   92|  69.9k|{
   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|  69.9k|  {
  117|       |    // static_cast<From>(To::max) rounds up to an out-of-range value when To has
  118|       |    // more significant bits than From's mantissa (e.g. double -> int64_t). In
  119|       |    // that case a plain `>` lets the rounded boundary through and the cast to To
  120|       |    // below overflows, so use a half-open upper bound to reject it first.
  121|  69.9k|    constexpr bool max_rounds_up =
  122|  69.9k|        std::numeric_limits<To>::digits > std::numeric_limits<From>::digits;
  123|  69.9k|    const From max_limit = static_cast<From>(std::numeric_limits<To>::max());
  124|  69.9k|    const bool over = max_rounds_up ? (from >= max_limit) : (from > max_limit);
  ------------------
  |  Branch (124:23): [True: 69.9k, Folded]
  ------------------
  125|  69.9k|    if(over || from < static_cast<From>(std::numeric_limits<To>::lowest()) ||
  ------------------
  |  Branch (125:8): [True: 2, False: 69.9k]
  |  Branch (125:16): [True: 3, False: 69.9k]
  ------------------
  126|  69.9k|       from != std::nearbyint(from))
  ------------------
  |  Branch (126:8): [True: 10, False: 69.9k]
  ------------------
  127|     15|    {
  128|     15|      throw std::runtime_error("Invalid floating point to integer conversion");
  129|     15|    }
  130|       |  }
  131|       |  // Handle other conversions
  132|       |  else
  133|       |  {
  134|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  135|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()))
  136|       |    {
  137|       |      throw std::runtime_error("Value outside numeric limits");
  138|       |    }
  139|       |    To as_target = static_cast<To>(from);
  140|       |    From back_to_source = static_cast<From>(as_target);
  141|       |    if(from != back_to_source)
  142|       |    {
  143|       |      throw std::runtime_error("Value truncated in conversion");
  144|       |    }
  145|       |  }
  146|  69.9k|}
_ZN7SafeAny7details13convertNumberIlbEEvRKT_RT0_:
  152|  1.39k|{
  153|  1.39k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|  1.39k|                                                                          "convertible");
  155|       |
  156|  1.39k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [True: 0, Folded]
  |  Branch (156:55): [True: 0, Folded]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|  1.39k|  {
  160|  1.39k|    if(source < 0)
  ------------------
  |  Branch (160:8): [True: 55, False: 1.34k]
  ------------------
  161|     55|    {
  162|     55|      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|     55|    }
  164|  1.39k|  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|       |  {
  172|       |    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|  1.39k|  {
  177|  1.39k|    checkLowerLimit<SRC, DST>(source);
  178|  1.39k|    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|       |  {
  201|       |    bool both_float =
  202|       |        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|       |    if(!both_float)
  205|       |    {
  206|       |      checkTruncation<SRC, DST>(source);
  207|       |    }
  208|       |    target = static_cast<DST>(source);
  209|       |  }
  210|  1.39k|}
_ZN7SafeAny7details15checkLowerLimitIlbEEvRKT_:
   76|  1.34k|{
   77|       |  if constexpr(std::is_same<To, bool>::value)
   78|  1.34k|  {
   79|  1.34k|    if(from != 0 && from != 1)
  ------------------
  |  Branch (79:8): [True: 746, False: 598]
  |  Branch (79:21): [True: 75, False: 671]
  ------------------
   80|     75|    {
   81|     75|      throw std::runtime_error("Implicit casting to bool is not allowed");
   82|     75|    }
   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.34k|}
_ZN7SafeAny7details13convertNumberIdbEEvRKT_RT0_:
  152|  1.01k|{
  153|  1.01k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|  1.01k|                                                                          "convertible");
  155|       |
  156|  1.01k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [Folded, False: 1.01k]
  |  Branch (156:55): [True: 0, Folded]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|  1.01k|  {
  160|  1.01k|    if(source < 0)
  ------------------
  |  Branch (160:8): [True: 1, False: 1.01k]
  ------------------
  161|      1|    {
  162|      1|      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|      1|    }
  164|  1.01k|  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|  1.01k|  {
  172|  1.01k|    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|       |  {
  177|       |    checkLowerLimit<SRC, DST>(source);
  178|       |    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|       |  {
  201|       |    bool both_float =
  202|       |        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|       |    if(!both_float)
  205|       |    {
  206|       |      checkTruncation<SRC, DST>(source);
  207|       |    }
  208|       |    target = static_cast<DST>(source);
  209|       |  }
  210|  1.01k|}

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

_ZNK2BT9LockedPtrINS_3AnyEEcvbEv:
   56|  73.4k|  {
   57|  73.4k|    return ref_ != nullptr;
   58|  73.4k|  }
_ZNK2BT9LockedPtrINS_3AnyEE3getEv:
   77|  73.0k|  {
   78|  73.0k|    return ref_;
   79|  73.0k|  }
_ZN2BT9LockedPtrINS_3AnyEED2Ev:
   32|  73.4k|  {
   33|  73.4k|    if(mutex_ != nullptr)
  ------------------
  |  Branch (33:8): [True: 73.0k, False: 446]
  ------------------
   34|  73.0k|    {
   35|  73.0k|      mutex_->unlock();
   36|  73.0k|    }
   37|  73.4k|  }
_ZN2BT9LockedPtrINS_3AnyEEC2Ev:
   24|    446|  LockedPtr() = default;
_ZN2BT9LockedPtrINS_3AnyEEC2EPS1_PSt5mutex:
   26|  73.0k|  LockedPtr(T* obj, std::mutex* obj_mutex) : ref_(obj), mutex_(obj_mutex)
   27|  73.0k|  {
   28|  73.0k|    mutex_->lock();
   29|  73.0k|  }

_ZNK2BT3Any8isNumberEv:
  361|   363k|{
  362|   363k|  return _any.type() == typeid(int64_t) || _any.type() == typeid(uint64_t) ||
  ------------------
  |  Branch (362:10): [True: 206k, False: 156k]
  |  Branch (362:44): [True: 0, False: 156k]
  ------------------
  363|   156k|         _any.type() == typeid(double);
  ------------------
  |  Branch (363:10): [True: 80.7k, False: 75.4k]
  ------------------
  364|   363k|}
_ZN2BT3AnyC2Ev:
   85|  60.0k|  Any() : _original_type(UndefinedAnyType)
   86|  60.0k|  {}
_ZN2BT3AnyD2Ev:
   88|  5.10M|  ~Any() = default;
_ZNK2BT3Any4castIdEET_v:
  176|   306k|  {
  177|   306k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (177:13): [True: 305k, False: 190]
  ------------------
  178|   305k|    {
  179|   305k|      return res.value();
  180|   305k|    }
  181|    190|    else
  182|    190|    {
  183|    190|      throw std::runtime_error(res.error());
  184|    190|    }
  185|   306k|  }
_ZNK2BT3Any7tryCastIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  537|   306k|{
  538|   306k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  539|   306k|                                              "can not cast to reference");
  540|       |
  541|   306k|  if(_any.empty())
  ------------------
  |  Branch (541:6): [True: 2, False: 306k]
  ------------------
  542|      2|  {
  543|      2|    throw std::runtime_error("Any::cast failed because it is empty");
  544|      2|  }
  545|       |
  546|   306k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (546:6): [True: 76.0k, False: 230k]
  ------------------
  547|  76.0k|  {
  548|  76.0k|    return linb::any_cast<T>(_any);
  549|  76.0k|  }
  550|       |
  551|       |  // special case when the output is an enum.
  552|       |  // We will try first a int conversion
  553|       |  if constexpr(std::is_enum_v<T>)
  554|       |  {
  555|       |    if(isNumber())
  556|       |    {
  557|       |      return static_cast<T>(convert<int>().value());
  558|       |    }
  559|       |    if(isString())
  560|       |    {
  561|       |      if(auto out = stringToNumber<int64_t>())
  562|       |      {
  563|       |        return static_cast<T>(out.value());
  564|       |      }
  565|       |    }
  566|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  567|       |  }
  568|       |
  569|   230k|  if(isString())
  ------------------
  |  Branch (569:6): [True: 49.3k, False: 180k]
  ------------------
  570|  49.3k|  {
  571|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  572|  49.3k|    {
  573|  49.3k|      if(auto out = stringToNumber<T>())
  ------------------
  |  Branch (573:15): [True: 49.2k, False: 168]
  ------------------
  574|  49.2k|      {
  575|  49.2k|        return out.value();
  576|  49.2k|      }
  577|    168|      else
  578|    168|      {
  579|    168|        return out;
  580|    168|      }
  581|  49.3k|    }
  582|  49.3k|  }
  583|       |
  584|   230k|  if(auto res = convert<T>())
  ------------------
  |  Branch (584:11): [True: 180k, False: 49.3k]
  ------------------
  585|   180k|  {
  586|   180k|    return std::move(res.value());
  587|   180k|  }
  588|  49.3k|  else
  589|  49.3k|  {
  590|  49.3k|    return res;
  591|  49.3k|  }
  592|   230k|}
_ZNK2BT3Any10castedTypeEv:
  207|   569k|  {
  208|   569k|    return _any.type();
  209|   569k|  }
_ZNK2BT3Any8isStringEv:
  148|   590k|  {
  149|   590k|    return _any.type() == typeid(SafeAny::SimpleString);
  150|   590k|  }
_ZNK2BT3Any14stringToNumberIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  437|  49.3k|{
  438|  49.3k|  static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "Expecting a "
  439|  49.3k|                                                                     "numeric type");
  440|       |
  441|  49.3k|  const auto str = linb::any_cast<SafeAny::SimpleString>(_any);
  442|       |#if __cpp_lib_to_chars >= 201611L
  443|       |  T out;
  444|       |  auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out);
  445|       |  if(err == std::errc())
  446|       |  {
  447|       |    return out;
  448|       |  }
  449|       |  else
  450|       |  {
  451|       |    return nonstd::make_unexpected("Any failed string to number conversion");
  452|       |  }
  453|       |#else
  454|  49.3k|  try
  455|  49.3k|  {
  456|       |    if constexpr(std::is_same_v<T, uint16_t>)
  457|       |    {
  458|       |      return std::stoul(str.toStdString());
  459|       |    }
  460|       |    if constexpr(std::is_integral_v<T>)
  461|       |    {
  462|       |      const int64_t val = std::stol(str.toStdString());
  463|       |      Any temp_any(val);
  464|       |      return temp_any.convert<T>();
  465|       |    }
  466|       |    if constexpr(std::is_floating_point_v<T>)
  467|  49.3k|    {
  468|       |      // std::stod honors LC_NUMERIC, so under a locale that uses ',' as decimal
  469|       |      // separator "3.5" would silently parse as 3. parseDouble reproduces the
  470|       |      // std::from_chars semantics of the branch above, on every platform.
  471|  49.3k|      double value = 0.0;
  472|  49.3k|      if(parseDouble(str.toStdStringView(), value, /*require_full_consumption=*/false))
  ------------------
  |  Branch (472:10): [True: 49.2k, False: 168]
  ------------------
  473|  49.2k|      {
  474|  49.2k|        return static_cast<T>(value);
  475|  49.2k|      }
  476|    168|      return nonstd::make_unexpected("Any failed string to number conversion");
  477|  49.3k|    }
  478|  49.3k|  }
  479|  49.3k|  catch(...)
  480|  49.3k|  {
  481|      0|    return nonstd::make_unexpected("Any failed string to number conversion");
  482|      0|  }
  483|      0|#endif
  484|      0|  return nonstd::make_unexpected("Any conversion from string failed");
  485|  49.3k|}
_ZNK2BT3Any7convertIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  510|   180k|{
  511|   180k|  using SafeAny::details::convertNumber;
  512|   180k|  DST out;
  513|       |
  514|   180k|  const auto& type = _any.type();
  515|       |
  516|   180k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (516:6): [True: 180k, False: 0]
  ------------------
  517|   180k|  {
  518|   180k|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  519|   180k|  }
  520|      0|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (520:11): [True: 0, False: 0]
  ------------------
  521|      0|  {
  522|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  523|      0|  }
  524|      0|  else if(type == typeid(double))
  ------------------
  |  Branch (524:11): [True: 0, False: 0]
  ------------------
  525|      0|  {
  526|      0|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  527|      0|  }
  528|      0|  else
  529|      0|  {
  530|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  531|      0|  }
  532|   180k|  return out;
  533|   180k|}
_ZNK2BT3Any4typeEv:
  201|  16.3k|  {
  202|  16.3k|    return _original_type;
  203|  16.3k|  }
_ZN2BT3AnyC2IiEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  125|  5.39k|    : _any(int64_t(value)), _original_type(typeid(T))
  126|  5.39k|  {}
_ZN2BT3AnyaSERKS0_:
  344|   107k|{
  345|   107k|  if(this != &other)
  ------------------
  |  Branch (345:6): [True: 107k, False: 0]
  ------------------
  346|   107k|  {
  347|   107k|    this->_any = other._any;
  348|   107k|    this->_original_type = other._original_type;
  349|   107k|  }
  350|   107k|  return *this;
  351|   107k|}
_ZN2BT3AnyaSEOS0_:
  354|  39.1k|{
  355|  39.1k|  this->_any = std::move(other._any);
  356|  39.1k|  this->_original_type = other._original_type;
  357|  39.1k|  return *this;
  358|  39.1k|}
_ZNK2BT3Any8copyIntoERS0_:
  372|  10.5k|{
  373|  10.5k|  if(dst.empty())
  ------------------
  |  Branch (373:6): [True: 0, False: 10.5k]
  ------------------
  374|      0|  {
  375|      0|    dst = *this;
  376|      0|    return;
  377|      0|  }
  378|       |
  379|  10.5k|  const auto& dst_type = dst.castedType();
  380|       |
  381|  10.5k|  if((castedType() == dst_type) || (isString() && dst.isString()))
  ------------------
  |  Branch (381:6): [True: 9.42k, False: 1.12k]
  |  Branch (381:37): [True: 7, False: 1.11k]
  |  Branch (381:51): [True: 0, False: 7]
  ------------------
  382|  9.42k|  {
  383|  9.42k|    dst._any = _any;
  384|  9.42k|  }
  385|  1.12k|  else if(isNumber() && dst.isNumber())
  ------------------
  |  Branch (385:11): [True: 1.11k, False: 7]
  |  Branch (385:25): [True: 1.06k, False: 50]
  ------------------
  386|  1.06k|  {
  387|  1.06k|    if(dst_type == typeid(int64_t))
  ------------------
  |  Branch (387:8): [True: 869, False: 196]
  ------------------
  388|    869|    {
  389|    869|      dst._any = cast<int64_t>();
  390|    869|    }
  391|    196|    else if(dst_type == typeid(uint64_t))
  ------------------
  |  Branch (391:13): [True: 0, False: 196]
  ------------------
  392|      0|    {
  393|      0|      dst._any = cast<uint64_t>();
  394|      0|    }
  395|    196|    else if(dst_type == typeid(double))
  ------------------
  |  Branch (395:13): [True: 196, False: 0]
  ------------------
  396|    196|    {
  397|    196|      dst._any = cast<double>();
  398|    196|    }
  399|      0|    else
  400|      0|    {
  401|      0|      throw std::runtime_error("Any::copyInto fails");
  402|      0|    }
  403|  1.06k|  }
  404|     57|  else
  405|     57|  {
  406|     57|    throw std::runtime_error("Any::copyInto fails");
  407|     57|  }
  408|  10.5k|}
_ZNK2BT3Any5emptyEv:
  212|   380k|  {
  213|   380k|    return _any.empty();
  214|   380k|  }
_ZNK2BT3Any4castIlEET_v:
  176|   138k|  {
  177|   138k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (177:13): [True: 138k, False: 15]
  ------------------
  178|   138k|    {
  179|   138k|      return res.value();
  180|   138k|    }
  181|     15|    else
  182|     15|    {
  183|     15|      throw std::runtime_error(res.error());
  184|     15|    }
  185|   138k|  }
_ZNK2BT3Any7tryCastIlEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  537|   138k|{
  538|   138k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  539|   138k|                                              "can not cast to reference");
  540|       |
  541|   138k|  if(_any.empty())
  ------------------
  |  Branch (541:6): [True: 0, False: 138k]
  ------------------
  542|      0|  {
  543|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  544|      0|  }
  545|       |
  546|   138k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (546:6): [True: 68.9k, False: 69.9k]
  ------------------
  547|  68.9k|  {
  548|  68.9k|    return linb::any_cast<T>(_any);
  549|  68.9k|  }
  550|       |
  551|       |  // special case when the output is an enum.
  552|       |  // We will try first a int conversion
  553|       |  if constexpr(std::is_enum_v<T>)
  554|       |  {
  555|       |    if(isNumber())
  556|       |    {
  557|       |      return static_cast<T>(convert<int>().value());
  558|       |    }
  559|       |    if(isString())
  560|       |    {
  561|       |      if(auto out = stringToNumber<int64_t>())
  562|       |      {
  563|       |        return static_cast<T>(out.value());
  564|       |      }
  565|       |    }
  566|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  567|       |  }
  568|       |
  569|  69.9k|  if(isString())
  ------------------
  |  Branch (569:6): [True: 0, False: 69.9k]
  ------------------
  570|      0|  {
  571|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  572|      0|    {
  573|      0|      if(auto out = stringToNumber<T>())
  ------------------
  |  Branch (573:15): [True: 0, False: 0]
  ------------------
  574|      0|      {
  575|      0|        return out.value();
  576|      0|      }
  577|      0|      else
  578|      0|      {
  579|      0|        return out;
  580|      0|      }
  581|      0|    }
  582|      0|  }
  583|       |
  584|  69.9k|  if(auto res = convert<T>())
  ------------------
  |  Branch (584:11): [True: 69.9k, False: 15]
  ------------------
  585|  69.9k|  {
  586|  69.9k|    return std::move(res.value());
  587|  69.9k|  }
  588|     15|  else
  589|     15|  {
  590|     15|    return res;
  591|     15|  }
  592|  69.9k|}
_ZN2BT3AnyC2IlEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  125|  1.33M|    : _any(int64_t(value)), _original_type(typeid(T))
  126|  1.33M|  {}
_ZNK2BT3Any7convertIlEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  510|  69.9k|{
  511|  69.9k|  using SafeAny::details::convertNumber;
  512|  69.9k|  DST out;
  513|       |
  514|  69.9k|  const auto& type = _any.type();
  515|       |
  516|  69.9k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (516:6): [True: 0, False: 69.9k]
  ------------------
  517|      0|  {
  518|      0|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  519|      0|  }
  520|  69.9k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (520:11): [True: 0, False: 69.9k]
  ------------------
  521|      0|  {
  522|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  523|      0|  }
  524|  69.9k|  else if(type == typeid(double))
  ------------------
  |  Branch (524:11): [True: 69.9k, False: 0]
  ------------------
  525|  69.9k|  {
  526|  69.9k|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  527|  69.9k|  }
  528|      0|  else
  529|      0|  {
  530|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  531|      0|  }
  532|  69.9k|  return out;
  533|  69.9k|}
_ZN2BT3AnyC2ERKd:
   97|   183k|  explicit Any(const double& value) : _any(value), _original_type(typeid(double))
   98|   183k|  {}
_ZN2BT3AnyC2IbEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  125|  5.39k|    : _any(int64_t(value)), _original_type(typeid(T))
  126|  5.39k|  {}
_ZN2BT3AnyC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  107|   183k|    : _any(SafeAny::SimpleString(str)), _original_type(typeid(std::string))
  108|   183k|  {}
_ZN2BT3AnyC2ERKS0_:
   90|  1.79M|  Any(const Any& other) : _any(other._any), _original_type(other._original_type)
   91|  1.79M|  {}
_ZN2BT3AnyC2EOS0_:
   94|  1.50M|    : _any(std::move(other._any)), _original_type(other._original_type)
   95|  1.50M|  {}
_ZN2BT3AnyC2ERKSt10type_index:
  128|  29.9k|  Any(const std::type_index& type) : _original_type(type)
  129|  29.9k|  {}
_ZNK2BT3Any4castINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEET_v:
  176|  81.8k|  {
  177|  81.8k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (177:13): [True: 81.8k, False: 0]
  ------------------
  178|  81.8k|    {
  179|  81.8k|      return res.value();
  180|  81.8k|    }
  181|      0|    else
  182|      0|    {
  183|      0|      throw std::runtime_error(res.error());
  184|      0|    }
  185|  81.8k|  }
_ZNK2BT3Any7tryCastINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEN6nonstd13expected_lite8expectedIT_S7_EEv:
  537|  81.8k|{
  538|  81.8k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  539|  81.8k|                                              "can not cast to reference");
  540|       |
  541|  81.8k|  if(_any.empty())
  ------------------
  |  Branch (541:6): [True: 0, False: 81.8k]
  ------------------
  542|      0|  {
  543|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  544|      0|  }
  545|       |
  546|  81.8k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (546:6): [True: 0, False: 81.8k]
  ------------------
  547|      0|  {
  548|      0|    return linb::any_cast<T>(_any);
  549|      0|  }
  550|       |
  551|       |  // special case when the output is an enum.
  552|       |  // We will try first a int conversion
  553|       |  if constexpr(std::is_enum_v<T>)
  554|       |  {
  555|       |    if(isNumber())
  556|       |    {
  557|       |      return static_cast<T>(convert<int>().value());
  558|       |    }
  559|       |    if(isString())
  560|       |    {
  561|       |      if(auto out = stringToNumber<int64_t>())
  562|       |      {
  563|       |        return static_cast<T>(out.value());
  564|       |      }
  565|       |    }
  566|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  567|       |  }
  568|       |
  569|  81.8k|  if(isString())
  ------------------
  |  Branch (569:6): [True: 78.4k, False: 3.36k]
  ------------------
  570|  78.4k|  {
  571|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  572|       |    {
  573|       |      if(auto out = stringToNumber<T>())
  574|       |      {
  575|       |        return out.value();
  576|       |      }
  577|       |      else
  578|       |      {
  579|       |        return out;
  580|       |      }
  581|       |    }
  582|  78.4k|  }
  583|       |
  584|  81.8k|  if(auto res = convert<T>())
  ------------------
  |  Branch (584:11): [True: 81.8k, False: 0]
  ------------------
  585|  81.8k|  {
  586|  81.8k|    return std::move(res.value());
  587|  81.8k|  }
  588|      0|  else
  589|      0|  {
  590|      0|    return res;
  591|      0|  }
  592|  81.8k|}
_ZNK2BT3Any7convertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEN6nonstd13expected_lite8expectedIT_S7_EEPNSt9enable_ifIXsr3std7is_sameISB_S7_EE5valueEvE4typeE:
  412|  81.8k|{
  413|  81.8k|  const auto& type = _any.type();
  414|       |
  415|  81.8k|  if(type == typeid(SafeAny::SimpleString))
  ------------------
  |  Branch (415:6): [True: 78.4k, False: 3.36k]
  ------------------
  416|  78.4k|  {
  417|  78.4k|    return linb::any_cast<SafeAny::SimpleString>(_any).toStdString();
  418|  78.4k|  }
  419|  3.36k|  else if(type == typeid(int64_t))
  ------------------
  |  Branch (419:11): [True: 1.14k, False: 2.22k]
  ------------------
  420|  1.14k|  {
  421|  1.14k|    return std::to_string(linb::any_cast<int64_t>(_any));
  422|  1.14k|  }
  423|  2.22k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (423:11): [True: 0, False: 2.22k]
  ------------------
  424|      0|  {
  425|      0|    return std::to_string(linb::any_cast<uint64_t>(_any));
  426|      0|  }
  427|  2.22k|  else if(type == typeid(double))
  ------------------
  |  Branch (427:11): [True: 2.22k, False: 0]
  ------------------
  428|  2.22k|  {
  429|  2.22k|    return std::to_string(linb::any_cast<double>(_any));
  430|  2.22k|  }
  431|       |
  432|      0|  return nonstd::make_unexpected(errorMsg<DST>());
  433|  81.8k|}
_ZNK2BT3Any6isTypeIN7SafeAny12SimpleStringEEEbv:
  155|    934|  {
  156|    934|    return _original_type == typeid(T);
  157|    934|  }
_ZNK2BT3Any4castIN7SafeAny12SimpleStringEEET_v:
  176|  19.4k|  {
  177|  19.4k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (177:13): [True: 19.4k, False: 0]
  ------------------
  178|  19.4k|    {
  179|  19.4k|      return res.value();
  180|  19.4k|    }
  181|      0|    else
  182|      0|    {
  183|      0|      throw std::runtime_error(res.error());
  184|      0|    }
  185|  19.4k|  }
_ZNK2BT3Any7tryCastIN7SafeAny12SimpleStringEEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  537|  19.4k|{
  538|  19.4k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  539|  19.4k|                                              "can not cast to reference");
  540|       |
  541|  19.4k|  if(_any.empty())
  ------------------
  |  Branch (541:6): [True: 0, False: 19.4k]
  ------------------
  542|      0|  {
  543|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  544|      0|  }
  545|       |
  546|  19.4k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (546:6): [True: 19.4k, False: 0]
  ------------------
  547|  19.4k|  {
  548|  19.4k|    return linb::any_cast<T>(_any);
  549|  19.4k|  }
  550|       |
  551|       |  // special case when the output is an enum.
  552|       |  // We will try first a int conversion
  553|       |  if constexpr(std::is_enum_v<T>)
  554|       |  {
  555|       |    if(isNumber())
  556|       |    {
  557|       |      return static_cast<T>(convert<int>().value());
  558|       |    }
  559|       |    if(isString())
  560|       |    {
  561|       |      if(auto out = stringToNumber<int64_t>())
  562|       |      {
  563|       |        return static_cast<T>(out.value());
  564|       |      }
  565|       |    }
  566|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  567|       |  }
  568|       |
  569|      0|  if(isString())
  ------------------
  |  Branch (569:6): [True: 0, False: 0]
  ------------------
  570|      0|  {
  571|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  572|       |    {
  573|       |      if(auto out = stringToNumber<T>())
  574|       |      {
  575|       |        return out.value();
  576|       |      }
  577|       |      else
  578|       |      {
  579|       |        return out;
  580|       |      }
  581|       |    }
  582|      0|  }
  583|       |
  584|      0|  if(auto res = convert<T>())
  ------------------
  |  Branch (584:11): [True: 0, False: 0]
  ------------------
  585|      0|  {
  586|      0|    return std::move(res.value());
  587|      0|  }
  588|      0|  else
  589|      0|  {
  590|      0|    return res;
  591|      0|  }
  592|      0|}
_ZNK2BT3Any4castIbEET_v:
  176|  2.41k|  {
  177|  2.41k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (177:13): [True: 2.28k, False: 131]
  ------------------
  178|  2.28k|    {
  179|  2.28k|      return res.value();
  180|  2.28k|    }
  181|    131|    else
  182|    131|    {
  183|    131|      throw std::runtime_error(res.error());
  184|    131|    }
  185|  2.41k|  }
_ZNK2BT3Any7tryCastIbEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  537|  2.41k|{
  538|  2.41k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  539|  2.41k|                                              "can not cast to reference");
  540|       |
  541|  2.41k|  if(_any.empty())
  ------------------
  |  Branch (541:6): [True: 0, False: 2.41k]
  ------------------
  542|      0|  {
  543|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  544|      0|  }
  545|       |
  546|  2.41k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (546:6): [True: 0, False: 2.41k]
  ------------------
  547|      0|  {
  548|      0|    return linb::any_cast<T>(_any);
  549|      0|  }
  550|       |
  551|       |  // special case when the output is an enum.
  552|       |  // We will try first a int conversion
  553|       |  if constexpr(std::is_enum_v<T>)
  554|       |  {
  555|       |    if(isNumber())
  556|       |    {
  557|       |      return static_cast<T>(convert<int>().value());
  558|       |    }
  559|       |    if(isString())
  560|       |    {
  561|       |      if(auto out = stringToNumber<int64_t>())
  562|       |      {
  563|       |        return static_cast<T>(out.value());
  564|       |      }
  565|       |    }
  566|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  567|       |  }
  568|       |
  569|  2.41k|  if(isString())
  ------------------
  |  Branch (569:6): [True: 0, False: 2.41k]
  ------------------
  570|      0|  {
  571|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  572|       |    {
  573|       |      if(auto out = stringToNumber<T>())
  574|       |      {
  575|       |        return out.value();
  576|       |      }
  577|       |      else
  578|       |      {
  579|       |        return out;
  580|       |      }
  581|       |    }
  582|      0|  }
  583|       |
  584|  2.41k|  if(auto res = convert<T>())
  ------------------
  |  Branch (584:11): [True: 2.28k, False: 131]
  ------------------
  585|  2.28k|  {
  586|  2.28k|    return std::move(res.value());
  587|  2.28k|  }
  588|    131|  else
  589|    131|  {
  590|    131|    return res;
  591|    131|  }
  592|  2.41k|}
_ZNK2BT3Any7convertIbEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  510|  2.41k|{
  511|  2.41k|  using SafeAny::details::convertNumber;
  512|  2.41k|  DST out;
  513|       |
  514|  2.41k|  const auto& type = _any.type();
  515|       |
  516|  2.41k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (516:6): [True: 1.39k, False: 1.01k]
  ------------------
  517|  1.39k|  {
  518|  1.39k|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  519|  1.39k|  }
  520|  1.01k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (520:11): [True: 0, False: 1.01k]
  ------------------
  521|      0|  {
  522|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  523|      0|  }
  524|  1.01k|  else if(type == typeid(double))
  ------------------
  |  Branch (524:11): [True: 1.01k, False: 0]
  ------------------
  525|  1.01k|  {
  526|  1.01k|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  527|  1.01k|  }
  528|      0|  else
  529|      0|  {
  530|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  531|      0|  }
  532|  2.41k|  return out;
  533|  2.41k|}

_ZN7SafeAny12SimpleStringC2ERKS0_:
   33|   523k|  SimpleString(const SimpleString& other) : SimpleString(other.data(), other.size())
   34|   523k|  {}
_ZNK7SafeAny12SimpleString4dataEv:
   87|   665k|  {
   88|   665k|    if(isSOO())
  ------------------
  |  Branch (88:8): [True: 542k, False: 123k]
  ------------------
   89|   542k|    {
   90|   542k|      return _storage.soo.data;
   91|   542k|    }
   92|   123k|    else
   93|   123k|    {
   94|   123k|      return _storage.str.data;
   95|   123k|    }
   96|   665k|  }
_ZNK7SafeAny12SimpleString5isSOOEv:
  158|  2.68M|  {
  159|  2.68M|    return (_storage.soo.capacity_left & IS_LONG_BIT) == 0;
  160|  2.68M|  }
_ZNK7SafeAny12SimpleString4sizeEv:
   99|   802k|  {
  100|   802k|    if(isSOO())
  ------------------
  |  Branch (100:8): [True: 654k, False: 148k]
  ------------------
  101|   654k|    {
  102|   654k|      return CAPACITY - _storage.soo.capacity_left;
  103|   654k|    }
  104|   148k|    else
  105|   148k|    {
  106|   148k|      return _storage.str.size & LONG_MASK;
  107|   148k|    }
  108|   802k|  }
_ZN7SafeAny12SimpleStringC2EPKcm:
   64|   707k|  {
   65|   707k|    createImpl(input_data, size);
   66|   707k|  }
_ZN7SafeAny12SimpleString10createImplEPKcm:
  187|   707k|  {
  188|   707k|    if(size > MAX_SIZE)
  ------------------
  |  Branch (188:8): [True: 13, False: 707k]
  ------------------
  189|     13|    {
  190|     13|      throw std::invalid_argument("size too large for a simple string");
  191|     13|    }
  192|       |
  193|   707k|    if(size > CAPACITY)
  ------------------
  |  Branch (193:8): [True: 130k, False: 576k]
  ------------------
  194|   130k|    {
  195|   130k|      _storage.str.size = size;
  196|   130k|      _storage.soo.capacity_left = IS_LONG_BIT;
  197|   130k|      _storage.str.data = new char[size + 1];  // NOLINT(cppcoreguidelines-owning-memory)
  198|   130k|      std::memcpy(_storage.str.data, input_data, size);
  199|   130k|      _storage.str.data[size] = '\0';
  200|   130k|    }
  201|   576k|    else
  202|   576k|    {
  203|   576k|      _storage.soo.capacity_left = uint8_t(CAPACITY - size);
  204|   576k|      if(size > 0)
  ------------------
  |  Branch (204:10): [True: 444k, False: 132k]
  ------------------
  205|   444k|      {
  206|   444k|        std::memcpy(_storage.soo.data, input_data, size);
  207|   444k|      }
  208|   576k|      if(size < CAPACITY)
  ------------------
  |  Branch (208:10): [True: 575k, False: 1.57k]
  ------------------
  209|   575k|      {
  210|   575k|        _storage.soo.data[size] = '\0';
  211|   575k|      }
  212|   576k|    }
  213|   707k|  }
_ZNK7SafeAny12SimpleString15toStdStringViewEv:
   82|  49.3k|  {
   83|  49.3k|    return size() > 0 ? std::string_view(data(), size()) : std::string_view();
  ------------------
  |  Branch (83:12): [True: 49.3k, False: 45]
  ------------------
   84|  49.3k|  }
_ZN7SafeAny12SimpleStringD2Ev:
   69|  1.21M|  {
   70|  1.21M|    if(!isSOO())
  ------------------
  |  Branch (70:8): [True: 130k, False: 1.08M]
  ------------------
   71|   130k|    {
   72|   130k|      delete[] _storage.str.data;
   73|   130k|    }
   74|  1.21M|    _storage.soo.capacity_left = CAPACITY;
   75|  1.21M|  }
_ZNK7SafeAny12SimpleString11toStdStringB5cxx11Ev:
   78|  78.4k|  {
   79|  78.4k|    return size() > 0 ? std::string(data(), size()) : std::string();
  ------------------
  |  Branch (79:12): [True: 74.9k, False: 3.55k]
  ------------------
   80|  78.4k|  }
_ZN7SafeAny12SimpleStringC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   27|   183k|  SimpleString(const std::string& str) : SimpleString(str.data(), str.size())
   28|   183k|  {}
_ZN7SafeAny12SimpleStringC2EOS0_:
   46|   508k|  SimpleString(SimpleString&& other) noexcept : SimpleString()
   47|   508k|  {
   48|   508k|    std::swap(_storage, other._storage);
   49|   508k|  }
_ZN7SafeAny12SimpleStringC2Ev:
   22|   508k|  {
   23|   508k|    _storage.soo.capacity_left = CAPACITY;
   24|   508k|    _storage.soo.data[0] = '\0';
   25|   508k|  }
_ZNK7SafeAny12SimpleStringeqERKS0_:
  111|  2.13k|  {
  112|  2.13k|    const size_t N = size();
  113|       |    // memcmp, not strncmp: the content may hold embedded NUL bytes, and strncmp
  114|       |    // stops at the first one, reporting two different strings of equal length as
  115|       |    // equal. It is also what operator< below compares with.
  116|  2.13k|    return other.size() == N && std::memcmp(data(), other.data(), N) == 0;
  ------------------
  |  Branch (116:12): [True: 1.28k, False: 848]
  |  Branch (116:33): [True: 799, False: 483]
  ------------------
  117|  2.13k|  }
_ZNK7SafeAny12SimpleStringleERKS0_:
  126|  2.33k|  {
  127|  2.33k|    return !(*this > other);
  128|  2.33k|  }
_ZNK7SafeAny12SimpleStringgeERKS0_:
  131|  1.46k|  {
  132|  1.46k|    return !(*this < other);
  133|  1.46k|  }
_ZNK7SafeAny12SimpleStringltERKS0_:
  136|  4.02k|  {
  137|  4.02k|    const size_t min_size = std::min(size(), other.size());
  138|  4.02k|    int cmp = std::memcmp(data(), other.data(), min_size);
  139|  4.02k|    if(cmp != 0)
  ------------------
  |  Branch (139:8): [True: 1.84k, False: 2.18k]
  ------------------
  140|  1.84k|    {
  141|  1.84k|      return cmp < 0;
  142|  1.84k|    }
  143|  2.18k|    return size() < other.size();
  144|  4.02k|  }
_ZNK7SafeAny12SimpleStringgtERKS0_:
  147|  3.55k|  {
  148|  3.55k|    const size_t min_size = std::min(size(), other.size());
  149|  3.55k|    int cmp = std::memcmp(data(), other.data(), min_size);
  150|  3.55k|    if(cmp != 0)
  ------------------
  |  Branch (150:8): [True: 1.92k, False: 1.62k]
  ------------------
  151|  1.92k|    {
  152|  1.92k|      return cmp > 0;
  153|  1.92k|    }
  154|  1.62k|    return size() > other.size();
  155|  3.55k|  }

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

_ZN2BT11parseDoubleESt17basic_string_viewIcSt11char_traitsIcEERdb:
  208|  54.7k|{
  209|       |#if defined(__cpp_lib_to_chars) && (__cpp_lib_to_chars >= 201611L)
  210|       |  // std::from_chars is locale-independent and thread-safe.
  211|       |  const char* begin = str.data();
  212|       |  const char* end = begin + str.size();
  213|       |  const auto [ptr, ec] = std::from_chars(begin, end, out);
  214|       |  if(ec != std::errc())
  215|       |  {
  216|       |    return false;
  217|       |  }
  218|       |  return !require_full_consumption || ptr == end;
  219|       |#else
  220|       |  // Apple's libc++ lacks the floating-point std::from_chars overload. Reproduce
  221|       |  // its std::chars_format::general semantics with strtod_l under a "C" locale
  222|       |  // created once (thread-safe, no global setlocale mutation), plus a guard that
  223|       |  // rejects the leading whitespace, leading '+', and hex floats that strtod
  224|       |  // would otherwise accept.
  225|  54.7k|  if(str.empty())
  ------------------
  |  Branch (225:6): [True: 45, False: 54.6k]
  ------------------
  226|     45|  {
  227|     45|    return false;
  228|     45|  }
  229|  54.6k|  const char first = str.front();
  230|  54.6k|  if(first == '+' || std::isspace(static_cast<unsigned char>(first)) != 0)
  ------------------
  |  Branch (230:6): [True: 1, False: 54.6k]
  |  Branch (230:22): [True: 2, False: 54.6k]
  ------------------
  231|      3|  {
  232|      3|    return false;
  233|      3|  }
  234|       |  // std::from_chars(general) does not recognise a "0x"/"0X" hex-float prefix; it
  235|       |  // parses only the leading "0" and stops at the 'x'. strtod would consume the
  236|       |  // whole hex float, so emulate from_chars here: the value is 0, and everything
  237|       |  // from the 'x' onward is unparsed (a failure only in the full-consumption case).
  238|  54.6k|  const std::size_t mantissa = (first == '-') ? 1u : 0u;
  ------------------
  |  Branch (238:32): [True: 142, False: 54.5k]
  ------------------
  239|  54.6k|  if(str.size() > mantissa + 1 && str[mantissa] == '0' &&
  ------------------
  |  Branch (239:6): [True: 40.6k, False: 13.9k]
  |  Branch (239:35): [True: 2.24k, False: 38.4k]
  ------------------
  240|  2.24k|     (str[mantissa + 1] == 'x' || str[mantissa + 1] == 'X'))
  ------------------
  |  Branch (240:7): [True: 328, False: 1.91k]
  |  Branch (240:35): [True: 194, False: 1.71k]
  ------------------
  241|    522|  {
  242|    522|    if(require_full_consumption)
  ------------------
  |  Branch (242:8): [True: 0, False: 522]
  ------------------
  243|      0|    {
  244|      0|      return false;
  245|      0|    }
  246|    522|    out = (first == '-') ? -0.0 : 0.0;
  ------------------
  |  Branch (246:11): [True: 6, False: 516]
  ------------------
  247|    522|    return true;
  248|    522|  }
  249|  54.1k|  static ::locale_t c_locale =
  250|  54.1k|      ::newlocale(LC_NUMERIC_MASK, "C", static_cast<::locale_t>(0));
  251|  54.1k|  if(c_locale == static_cast<::locale_t>(0))
  ------------------
  |  Branch (251:6): [True: 0, False: 54.1k]
  ------------------
  252|      0|  {
  253|      0|    return false;
  254|      0|  }
  255|       |  // strtod_l needs a null-terminated buffer.
  256|  54.1k|  const std::string buffer(str.data(), str.size());
  257|  54.1k|  errno = 0;
  258|  54.1k|  char* parse_end = nullptr;
  259|  54.1k|  const double value = ::strtod_l(buffer.c_str(), &parse_end, c_locale);
  260|  54.1k|  if(parse_end == buffer.c_str() || errno == ERANGE)
  ------------------
  |  Branch (260:6): [True: 119, False: 54.0k]
  |  Branch (260:37): [True: 64, False: 53.9k]
  ------------------
  261|    183|  {
  262|    183|    return false;
  263|    183|  }
  264|  53.9k|  if(require_full_consumption && parse_end != buffer.c_str() + buffer.size())
  ------------------
  |  Branch (264:6): [True: 0, False: 53.9k]
  |  Branch (264:34): [True: 0, False: 0]
  ------------------
  265|      0|  {
  266|      0|    return false;
  267|      0|  }
  268|  53.9k|  out = value;
  269|  53.9k|  return true;
  270|  53.9k|#endif
  271|  53.9k|}
_ZN2BT17convertFromStringIdEET_St17basic_string_viewIcSt11char_traitsIcEE:
  275|  5.35k|{
  276|  5.35k|  double result = 0;
  277|  5.35k|  if(!parseDouble(str, result, /*require_full_consumption=*/false))
  ------------------
  |  Branch (277:6): [True: 63, False: 5.29k]
  ------------------
  278|     63|  {
  279|     63|    throw RuntimeError(StrCat("Can't convert string [", str, "] to double"));
  280|     63|  }
  281|  5.29k|  return result;
  282|  5.35k|}
_ZNK2BT8TypeInfo4typeEv:
  500|  36.8k|{
  501|  36.8k|  return type_info_;
  502|  36.8k|}
_ZN2BT9StartWithESt17basic_string_viewIcSt11char_traitsIcEEc:
  663|   258k|{
  664|   258k|  return str.size() >= 1 && str[0] == prefix;
  ------------------
  |  Branch (664:10): [True: 188k, False: 69.9k]
  |  Branch (664:29): [True: 76.1k, False: 112k]
  ------------------
  665|   258k|}

_ZN2BT10Blackboard12getAnyLockedERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  117|  73.4k|{
  118|  73.4k|  if(auto entry = getEntry(key))
  ------------------
  |  Branch (118:11): [True: 73.0k, False: 446]
  ------------------
  119|  73.0k|  {
  120|  73.0k|    return AnyPtrLocked(&entry->value, &entry->entry_mutex);
  121|  73.0k|  }
  122|    446|  return {};
  123|  73.4k|}
_ZNK2BT10Blackboard8getEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  147|   198k|{
  148|       |  // special syntax: "@" will always refer to the root BB
  149|   198k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (149:6): [True: 73.5k, False: 125k]
  ------------------
  150|  73.5k|  {
  151|  73.5k|    return rootBlackboard()->getEntry(key.substr(1, key.size() - 1));
  152|  73.5k|  }
  153|       |
  154|   125k|  {
  155|   125k|    const std::shared_lock<std::shared_mutex> storage_lock(storage_mutex_);
  156|   125k|    auto it = storage_.find(key);
  157|   125k|    if(it != storage_.end())
  ------------------
  |  Branch (157:8): [True: 94.8k, False: 30.4k]
  ------------------
  158|  94.8k|    {
  159|  94.8k|      return it->second;
  160|  94.8k|    }
  161|   125k|  }
  162|       |  // not found. Try autoremapping
  163|  30.4k|  if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (163:11): [True: 0, False: 30.4k]
  ------------------
  164|      0|  {
  165|      0|    auto remap_it = internal_to_external_.find(key);
  166|      0|    if(remap_it != internal_to_external_.cend())
  ------------------
  |  Branch (166:8): [True: 0, False: 0]
  ------------------
  167|      0|    {
  168|      0|      auto const& new_key = remap_it->second;
  169|      0|      return parent->getEntry(new_key);
  170|      0|    }
  171|      0|    if(autoremapping_ && !IsPrivateKey(key))
  ------------------
  |  Branch (171:8): [True: 0, False: 0]
  |  Branch (171:26): [True: 0, False: 0]
  ------------------
  172|      0|    {
  173|      0|      return parent->getEntry(key);
  174|      0|    }
  175|      0|  }
  176|  30.4k|  return {};
  177|  30.4k|}
_ZN2BT10Blackboard8getEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  180|   125k|{
  181|   125k|  return static_cast<const Blackboard&>(*this).getEntry(key);
  182|   125k|}
_ZN2BT10Blackboard9entryInfoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  185|    664|{
  186|    664|  auto entry = getEntry(key);
  187|    664|  return (!entry) ? nullptr : &(entry->info);
  ------------------
  |  Branch (187:10): [True: 0, False: 664]
  ------------------
  188|    664|}
_ZN2BT10Blackboard11createEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_8TypeInfoE:
  271|  8.34k|{
  272|  8.34k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (272:6): [True: 2.65k, False: 5.69k]
  ------------------
  273|  2.65k|  {
  274|  2.65k|    if(key.find('@', 1) != std::string::npos)
  ------------------
  |  Branch (274:8): [True: 0, False: 2.65k]
  ------------------
  275|      0|    {
  276|      0|      throw LogicError("Character '@' used multiple times in the key");
  277|      0|    }
  278|  2.65k|    rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
  279|  2.65k|  }
  280|  5.69k|  else
  281|  5.69k|  {
  282|  5.69k|    createEntryImpl(key, info);
  283|  5.69k|  }
  284|  8.34k|}
_ZN2BT10Blackboard15createEntryImplERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_8TypeInfoE:
  396|  29.9k|{
  397|       |  // special syntax: "@" always refers to the root blackboard, the same
  398|       |  // redirection getEntry() applies. Without it, a key remapped to a root
  399|       |  // entry (port="{@foo}") is created here as a literal "@foo" entry that
  400|       |  // getEntry() then strips to "foo" and can never find again.
  401|  29.9k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (401:6): [True: 0, False: 29.9k]
  ------------------
  402|      0|  {
  403|      0|    return rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
  404|      0|  }
  405|       |
  406|       |  // Bound the lifetime of the entries that were removed while locked
  407|  29.9k|  if(GetRetiredEntries().count != 0)
  ------------------
  |  Branch (407:6): [True: 0, False: 29.9k]
  ------------------
  408|      0|  {
  409|      0|    SweepRetiredEntries();
  410|      0|  }
  411|       |
  412|  29.9k|  const std::unique_lock storage_lock(storage_mutex_);
  413|       |  // This function might be called recursively, when we do remapping, because we move
  414|       |  // to the top scope to find already existing  entries
  415|       |
  416|       |  // search if exists already
  417|  29.9k|  auto storage_it = storage_.find(key);
  418|  29.9k|  if(storage_it != storage_.end())
  ------------------
  |  Branch (418:6): [True: 0, False: 29.9k]
  ------------------
  419|      0|  {
  420|      0|    const auto& prev_info = storage_it->second->info;
  421|      0|    if(prev_info.type() != info.type() && prev_info.isStronglyTyped() &&
  ------------------
  |  Branch (421:8): [True: 0, False: 0]
  |  Branch (421:43): [True: 0, False: 0]
  ------------------
  422|      0|       info.isStronglyTyped())
  ------------------
  |  Branch (422:8): [True: 0, False: 0]
  ------------------
  423|      0|    {
  424|      0|      auto msg = StrCat("Blackboard entry [", key,
  425|      0|                        "]: once declared, the type of a port"
  426|      0|                        " shall not change. Previously declared type [",
  427|      0|                        BT::demangle(prev_info.type()), "], current type [",
  428|      0|                        BT::demangle(info.type()), "]");
  429|       |
  430|      0|      throw LogicError(msg);
  431|      0|    }
  432|      0|    return storage_it->second;
  433|      0|  }
  434|       |
  435|       |  // manual remapping first
  436|  29.9k|  auto remapping_it = internal_to_external_.find(key);
  437|  29.9k|  if(remapping_it != internal_to_external_.end())
  ------------------
  |  Branch (437:6): [True: 0, False: 29.9k]
  ------------------
  438|      0|  {
  439|      0|    const auto& remapped_key = remapping_it->second;
  440|      0|    if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (440:13): [True: 0, False: 0]
  ------------------
  441|      0|    {
  442|      0|      return parent->createEntryImpl(remapped_key, info);
  443|      0|    }
  444|      0|    throw RuntimeError("Missing parent blackboard");
  445|      0|  }
  446|       |  // autoremapping second (excluding private keys)
  447|  29.9k|  if(autoremapping_ && !IsPrivateKey(key))
  ------------------
  |  Branch (447:6): [True: 0, False: 29.9k]
  |  Branch (447:24): [True: 0, False: 0]
  ------------------
  448|      0|  {
  449|      0|    if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (449:13): [True: 0, False: 0]
  ------------------
  450|      0|    {
  451|      0|      return parent->createEntryImpl(key, info);
  452|      0|    }
  453|      0|    throw RuntimeError("Missing parent blackboard");
  454|      0|  }
  455|       |  // not remapped, not found. Create locally.
  456|       |
  457|  29.9k|  auto entry = MakeEntry(info);
  458|       |  // even if empty, let's assign to it a default type
  459|  29.9k|  entry->value = Any(info.type());
  460|  29.9k|  storage_.insert({ key, entry });
  461|  29.9k|  return entry;
  462|  29.9k|}
_ZN2BT10Blackboard14rootBlackboardEv:
  500|  2.65k|{
  501|  2.65k|  auto bb = static_cast<const Blackboard&>(*this).rootBlackboard();
  502|       |  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
  503|  2.65k|  return const_cast<Blackboard*>(bb);
  504|  2.65k|}
_ZNK2BT10Blackboard14rootBlackboardEv:
  507|  76.1k|{
  508|  76.1k|  const Blackboard* bb = this;
  509|  76.1k|  Blackboard::Ptr prev = parent_bb_.lock();
  510|  76.1k|  while(prev)
  ------------------
  |  Branch (510:9): [True: 0, False: 76.1k]
  ------------------
  511|      0|  {
  512|      0|    bb = prev.get();
  513|      0|    prev = bb->parent_bb_.lock();
  514|      0|  }
  515|  76.1k|  return bb;
  516|  76.1k|}
blackboard.cpp:_ZN2BT12_GLOBAL__N_19MakeEntryERKNS_8TypeInfoE:
  106|  29.9k|{
  107|  29.9k|  return { new Blackboard::Entry(info), &RetireEntry };
  108|  29.9k|}
blackboard.cpp:_ZN2BT12_GLOBAL__N_111RetireEntryEPNS_10Blackboard5EntryE:
   95|  29.9k|{
   96|       |  // Common case: nothing is parked and nobody holds this entry
   97|  29.9k|  if(GetRetiredEntries().count == 0 && IsUnlocked(retired))
  ------------------
  |  Branch (97:6): [True: 29.9k, False: 0]
  |  Branch (97:40): [True: 29.9k, False: 0]
  ------------------
   98|  29.9k|  {
   99|  29.9k|    delete retired;  // NOLINT(cppcoreguidelines-owning-memory)
  100|  29.9k|    return;
  101|  29.9k|  }
  102|      0|  SweepRetiredEntries(retired);
  103|      0|}
blackboard.cpp:_ZN2BT12_GLOBAL__N_110IsUnlockedEPNS_10Blackboard5EntryE:
   51|  29.9k|{
   52|  29.9k|  if(entry->entry_mutex.try_lock())
  ------------------
  |  Branch (52:6): [True: 29.9k, False: 0]
  ------------------
   53|  29.9k|  {
   54|  29.9k|    entry->entry_mutex.unlock();
   55|  29.9k|    return true;
   56|  29.9k|  }
   57|      0|  return false;
   58|  29.9k|}
blackboard.cpp:_ZN2BT12_GLOBAL__N_117GetRetiredEntriesEv:
   37|  59.8k|{
   38|       |  // Never destroyed: a Blackboard with static storage duration may be
   39|       |  // destroyed after this object during program exit.
   40|       |  // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
   41|  59.8k|  static auto* const instance = new RetiredEntries();
   42|  59.8k|  return *instance;
   43|  59.8k|}

_ZN2BT9Scripting15parseStatementsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  448|  12.3k|{
  449|  12.3k|  auto tokens = tokenize(script);
  450|  12.3k|  ScriptParser parser(std::move(tokens));
  451|  12.3k|  return parser.parseAll();
  452|  12.3k|}
_ZN2BT11ParseScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  459|  6.94k|{
  460|  6.94k|  try
  461|  6.94k|  {
  462|  6.94k|    auto exprs = Scripting::parseStatements(script);
  463|  6.94k|    if(exprs.empty())
  ------------------
  |  Branch (463:8): [True: 62, False: 6.87k]
  ------------------
  464|     62|    {
  465|     62|      return nonstd::make_unexpected("Empty Script");
  466|     62|    }
  467|  6.87k|    return [exprs = std::move(exprs), script](Ast::Environment& env) {
  468|  6.87k|      try
  469|  6.87k|      {
  470|  6.87k|        for(size_t i = 0; i < exprs.size() - 1; ++i)
  471|  6.87k|        {
  472|  6.87k|          exprs[i]->evaluate(env);
  473|  6.87k|        }
  474|  6.87k|        return exprs.back()->evaluate(env);
  475|  6.87k|      }
  476|  6.87k|      catch(RuntimeError& err)
  477|  6.87k|      {
  478|  6.87k|        throw RuntimeError(StrCat("Error in script [", script, "]\n", err.what()));
  479|  6.87k|      }
  480|  6.87k|    };
  481|  6.94k|  }
  482|  6.94k|  catch(RuntimeError& err)
  483|  6.94k|  {
  484|  3.02k|    return nonstd::make_unexpected(err.what());
  485|  3.02k|  }
  486|  6.94k|}
_ZN2BT21ParseScriptAndExecuteERNS_3Ast11EnvironmentERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  489|  5.39k|{
  490|  5.39k|  auto executor = ParseScript(script);
  491|  5.39k|  if(executor)
  ------------------
  |  Branch (491:6): [True: 3.85k, False: 1.54k]
  ------------------
  492|  3.85k|  {
  493|  3.85k|    try
  494|  3.85k|    {
  495|  3.85k|      return executor.value()(env);
  496|  3.85k|    }
  497|  3.85k|    catch(RuntimeError& err)
  498|  3.85k|    {
  499|    996|      return nonstd::make_unexpected(err.what());
  500|    996|    }
  501|  3.85k|  }
  502|  1.54k|  return nonstd::make_unexpected(executor.error());
  503|  5.39k|}
_ZN2BT14ValidateScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  506|  5.39k|{
  507|  5.39k|  try
  508|  5.39k|  {
  509|  5.39k|    auto exprs = Scripting::parseStatements(script);
  510|  5.39k|    if(exprs.empty())
  ------------------
  |  Branch (510:8): [True: 31, False: 5.36k]
  ------------------
  511|     31|    {
  512|     31|      return nonstd::make_unexpected("Empty Script");
  513|     31|    }
  514|  5.36k|    return {};
  515|  5.39k|  }
  516|  5.39k|  catch(RuntimeError& err)
  517|  5.39k|  {
  518|  1.51k|    return nonstd::make_unexpected(err.what());
  519|  1.51k|  }
  520|  5.39k|}
_ZN2BT9Scripting12ScriptParserC2ESt6vectorINS0_5TokenESaIS3_EE:
   28|  12.3k|  explicit ScriptParser(std::vector<Token> tokens) : tokens_(std::move(tokens))
   29|  12.3k|  {}
_ZN2BT9Scripting12ScriptParser8parseAllEv:
   32|  12.3k|  {
   33|  12.3k|    std::vector<Ast::expr_ptr> stmts;
   34|  3.53M|    while(!atEnd())
  ------------------
  |  Branch (34:11): [True: 3.51M, False: 12.3k]
  ------------------
   35|  3.51M|    {
   36|  3.51M|      stmts.push_back(parseExpr(0));
   37|       |      // consume optional semicolons between statements
   38|  3.52M|      while(check(TokenType::Semicolon))
  ------------------
  |  Branch (38:13): [True: 6.20k, False: 3.51M]
  ------------------
   39|  6.20k|      {
   40|  6.20k|        advance();
   41|  6.20k|      }
   42|  3.51M|    }
   43|  12.3k|    return stmts;
   44|  12.3k|  }
_ZNK2BT9Scripting12ScriptParser5atEndEv:
   81|  11.1M|  {
   82|  11.1M|    return peek().type == TokenType::EndOfInput;
   83|  11.1M|  }
_ZNK2BT9Scripting12ScriptParser4peekEv:
   68|  27.7M|  {
   69|  27.7M|    return tokens_[current_];
   70|  27.7M|  }
_ZN2BT9Scripting12ScriptParser9parseExprEi:
  269|  5.56M|  {
  270|       |    // Bound the recursion so a deeply nested expression can't overflow the
  271|       |    // stack. Every open paren / unary prefix / right-hand operand adds one
  272|       |    // parseExpr frame; depth_ is decremented before the normal return below so
  273|       |    // it tracks the current nesting rather than the total call count. A parse
  274|       |    // failure throws and discards the parser, so the error paths need no reset.
  275|  5.56M|    if(++depth_ > kMaxNestingDepth)
  ------------------
  |  Branch (275:8): [True: 27, False: 5.56M]
  ------------------
  276|     27|    {
  277|     27|      throw RuntimeError(StrCat("Parse error at position ", std::to_string(peek().pos),
  278|     27|                                ": expression nesting is too deep (limit ",
  279|     27|                                std::to_string(kMaxNestingDepth), ")"));
  280|     27|    }
  281|       |
  282|  5.56M|    auto left = parsePrefix();
  283|       |
  284|  5.95M|    while(true)
  ------------------
  |  Branch (284:11): [True: 5.92M, Folded]
  ------------------
  285|  5.92M|    {
  286|  5.92M|      auto tokType = peek().type;
  287|  5.92M|      int lbp = leftBP(tokType);
  288|  5.92M|      if(lbp < 0 || lbp < minBP)
  ------------------
  |  Branch (288:10): [True: 3.59M, False: 2.33M]
  |  Branch (288:21): [True: 1.87M, False: 453k]
  ------------------
  289|  5.47M|      {
  290|  5.47M|        break;
  291|  5.47M|      }
  292|       |
  293|       |      // Assignment (non-associative: parse once, then break)
  294|   453k|      if(isAssignment(tokType))
  ------------------
  |  Branch (294:10): [True: 56.5k, False: 396k]
  ------------------
  295|  56.5k|      {
  296|  56.5k|        left = parseAssignment(std::move(left));
  297|  56.5k|        break;
  298|  56.5k|      }
  299|       |
  300|       |      // Ternary (non-associative: parse once, then break)
  301|   396k|      if(tokType == TokenType::Question)
  ------------------
  |  Branch (301:10): [True: 7.39k, False: 389k]
  ------------------
  302|  7.39k|      {
  303|  7.39k|        left = parseTernary(std::move(left));
  304|  7.39k|        break;
  305|  7.39k|      }
  306|       |
  307|       |      // Chained comparison
  308|   389k|      if(isComparison(tokType))
  ------------------
  |  Branch (308:10): [True: 51.0k, False: 338k]
  ------------------
  309|  51.0k|      {
  310|  51.0k|        left = parseChainedComparison(std::move(left));
  311|  51.0k|        continue;
  312|  51.0k|      }
  313|       |
  314|       |      // Regular left-associative binary operator
  315|   338k|      const auto& opTok = advance();
  316|       |      // Right BP = LBP + 1 for left-associativity
  317|   338k|      auto right = parseExpr(lbp + 1);
  318|   338k|      left = makeBinary(std::move(left), opTok.type, std::move(right));
  319|   338k|    }
  320|       |
  321|  5.56M|    --depth_;
  322|  5.56M|    return left;
  323|  5.56M|  }
_ZN2BT9Scripting12ScriptParser11parsePrefixEv:
  172|  5.56M|  {
  173|  5.56M|    const auto& tok = peek();
  174|       |
  175|       |    // Unary minus
  176|  5.56M|    if(tok.type == TokenType::Minus)
  ------------------
  |  Branch (176:8): [True: 7.67k, False: 5.55M]
  ------------------
  177|  7.67k|    {
  178|  7.67k|      advance();
  179|  7.67k|      auto operand = parseExpr(kPrefixBP);
  180|  7.67k|      return std::make_shared<Ast::ExprUnaryArithmetic>(Ast::ExprUnaryArithmetic::negate,
  181|  7.67k|                                                        std::move(operand));
  182|  7.67k|    }
  183|       |    // Bitwise complement
  184|  5.55M|    if(tok.type == TokenType::Tilde)
  ------------------
  |  Branch (184:8): [True: 7.75k, False: 5.55M]
  ------------------
  185|  7.75k|    {
  186|  7.75k|      advance();
  187|  7.75k|      auto operand = parseExpr(kPrefixBP);
  188|  7.75k|      return std::make_shared<Ast::ExprUnaryArithmetic>(
  189|  7.75k|          Ast::ExprUnaryArithmetic::complement, std::move(operand));
  190|  7.75k|    }
  191|       |    // Logical NOT
  192|  5.55M|    if(tok.type == TokenType::Bang)
  ------------------
  |  Branch (192:8): [True: 11.4k, False: 5.53M]
  ------------------
  193|  11.4k|    {
  194|  11.4k|      advance();
  195|  11.4k|      auto operand = parseExpr(kPrefixBP);
  196|  11.4k|      return std::make_shared<Ast::ExprUnaryArithmetic>(
  197|  11.4k|          Ast::ExprUnaryArithmetic::logical_not, std::move(operand));
  198|  11.4k|    }
  199|       |    // Parenthesized expression
  200|  5.53M|    if(tok.type == TokenType::LeftParen)
  ------------------
  |  Branch (200:8): [True: 13.8k, False: 5.52M]
  ------------------
  201|  13.8k|    {
  202|  13.8k|      advance();
  203|  13.8k|      auto expr = parseExpr(0);
  204|  13.8k|      expect(TokenType::RightParen, "expected ')'");
  205|  13.8k|      return expr;
  206|  13.8k|    }
  207|       |    // Boolean literal
  208|  5.52M|    if(tok.type == TokenType::Boolean)
  ------------------
  |  Branch (208:8): [True: 1.76k, False: 5.52M]
  ------------------
  209|  1.76k|    {
  210|  1.76k|      advance();
  211|  1.76k|      double val = (tok.text == "true") ? 1.0 : 0.0;
  ------------------
  |  Branch (211:20): [True: 871, False: 898]
  ------------------
  212|  1.76k|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  213|  1.76k|    }
  214|       |    // Integer literal
  215|  5.52M|    if(tok.type == TokenType::Integer)
  ------------------
  |  Branch (215:8): [True: 1.33M, False: 4.18M]
  ------------------
  216|  1.33M|    {
  217|  1.33M|      advance();
  218|  1.33M|      int64_t val = 0;
  219|  1.33M|      const char* first = tok.text.data();
  220|  1.33M|      const char* last = first + tok.text.size();
  221|  1.33M|      const bool is_hex = tok.text.size() > 2 && tok.text[0] == '0' &&
  ------------------
  |  Branch (221:27): [True: 18.0k, False: 1.31M]
  |  Branch (221:50): [True: 3.45k, False: 14.6k]
  ------------------
  222|  3.45k|                          (tok.text[1] == 'x' || tok.text[1] == 'X');
  ------------------
  |  Branch (222:28): [True: 952, False: 2.50k]
  |  Branch (222:50): [True: 1.72k, False: 780]
  ------------------
  223|  1.33M|      const auto [ptr, ec] = is_hex ? std::from_chars(first + 2, last, val, 16) :
  ------------------
  |  Branch (223:30): [True: 2.67k, False: 1.33M]
  ------------------
  224|  1.33M|                                      std::from_chars(first, last, val, 10);
  225|       |      // The tokenizer already guarantees the literal is made of (hex) digits, so
  226|       |      // the only remaining failure is result_out_of_range. from_chars leaves val
  227|       |      // untouched in that case, which would otherwise turn a literal like
  228|       |      // 0xFFFFFFFFFFFFFFFF into a silent 0.
  229|  1.33M|      if(ec != std::errc() || ptr != last)
  ------------------
  |  Branch (229:10): [True: 540, False: 1.33M]
  |  Branch (229:31): [True: 0, False: 1.33M]
  ------------------
  230|    540|      {
  231|    540|        throw RuntimeError(StrCat("Integer literal '", tok.text, "' at position ",
  232|    540|                                  std::to_string(tok.pos),
  233|    540|                                  " is out of range for a 64-bit integer"));
  234|    540|      }
  235|  1.33M|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  236|  1.33M|    }
  237|       |    // Real literal
  238|  4.18M|    if(tok.type == TokenType::Real)
  ------------------
  |  Branch (238:8): [True: 5.35k, False: 4.18M]
  ------------------
  239|  5.35k|    {
  240|  5.35k|      advance();
  241|  5.35k|      double val = convertFromString<double>(tok.text);
  242|  5.35k|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  243|  5.35k|    }
  244|       |    // String literal
  245|  4.18M|    if(tok.type == TokenType::String)
  ------------------
  |  Branch (245:8): [True: 163k, False: 4.02M]
  ------------------
  246|   163k|    {
  247|   163k|      advance();
  248|   163k|      return std::make_shared<Ast::ExprLiteral>(Any(std::string(tok.text)));
  249|   163k|    }
  250|       |    // Identifier
  251|  4.02M|    if(tok.type == TokenType::Identifier)
  ------------------
  |  Branch (251:8): [True: 4.01M, False: 3.55k]
  ------------------
  252|  4.01M|    {
  253|  4.01M|      advance();
  254|  4.01M|      return std::make_shared<Ast::ExprName>(std::string(tok.text));
  255|  4.01M|    }
  256|       |    // Error token from tokenizer
  257|  3.55k|    if(tok.type == TokenType::Error)
  ------------------
  |  Branch (257:8): [True: 1.82k, False: 1.73k]
  ------------------
  258|  1.82k|    {
  259|  1.82k|      throw RuntimeError(
  260|  1.82k|          StrCat("Invalid token '", tok.text, "' at position ", std::to_string(tok.pos)));
  261|  1.82k|    }
  262|       |
  263|  1.73k|    throw RuntimeError(StrCat("Expected operand at position ", std::to_string(tok.pos),
  264|  1.73k|                              " (got '", tok.text, "')"));
  265|  3.55k|  }
_ZN2BT9Scripting12ScriptParser6expectENS0_9TokenTypeEPKc:
   91|  7.74k|  {
   92|  7.74k|    if(!check(type))
  ------------------
  |  Branch (92:8): [True: 351, False: 7.39k]
  ------------------
   93|    351|    {
   94|    351|      throw RuntimeError(StrCat("Parse error at position ", std::to_string(peek().pos),
   95|    351|                                ": ", msg, " (got '", peek().text, "')"));
   96|    351|    }
   97|  7.39k|    return advance();
   98|  7.74k|  }
_ZN2BT9Scripting12ScriptParser6leftBPENS0_9TokenTypeE:
  105|  5.92M|  {
  106|  5.92M|    switch(type)
  107|  5.92M|    {
  108|       |      // Assignment (level 1, non-associative)
  109|  21.7k|      case TokenType::ColonEqual:
  ------------------
  |  Branch (109:7): [True: 21.7k, False: 5.90M]
  ------------------
  110|  34.0k|      case TokenType::Equal:
  ------------------
  |  Branch (110:7): [True: 12.3k, False: 5.91M]
  ------------------
  111|  51.4k|      case TokenType::PlusEqual:
  ------------------
  |  Branch (111:7): [True: 17.3k, False: 5.90M]
  ------------------
  112|  53.0k|      case TokenType::MinusEqual:
  ------------------
  |  Branch (112:7): [True: 1.67k, False: 5.92M]
  ------------------
  113|  55.7k|      case TokenType::StarEqual:
  ------------------
  |  Branch (113:7): [True: 2.63k, False: 5.92M]
  ------------------
  114|  57.3k|      case TokenType::SlashEqual:
  ------------------
  |  Branch (114:7): [True: 1.61k, False: 5.92M]
  ------------------
  115|  57.3k|        return kAssignmentBP;
  116|       |      // Ternary (level 2, non-associative)
  117|  9.00k|      case TokenType::Question:
  ------------------
  |  Branch (117:7): [True: 9.00k, False: 5.91M]
  ------------------
  118|  9.00k|        return kTernaryBP;
  119|       |      // Logical OR (level 3)
  120|  2.68k|      case TokenType::PipePipe:
  ------------------
  |  Branch (120:7): [True: 2.68k, False: 5.92M]
  ------------------
  121|  2.68k|        return 6;
  122|       |      // Logical AND (level 4)
  123|  2.04k|      case TokenType::AmpAmp:
  ------------------
  |  Branch (123:7): [True: 2.04k, False: 5.92M]
  ------------------
  124|  2.04k|        return 8;
  125|       |      // Comparison (level 5, chainable)
  126|  7.18k|      case TokenType::EqualEqual:
  ------------------
  |  Branch (126:7): [True: 7.18k, False: 5.92M]
  ------------------
  127|  47.9k|      case TokenType::BangEqual:
  ------------------
  |  Branch (127:7): [True: 40.7k, False: 5.88M]
  ------------------
  128|   407k|      case TokenType::Less:
  ------------------
  |  Branch (128:7): [True: 359k, False: 5.56M]
  ------------------
  129|  1.57M|      case TokenType::Greater:
  ------------------
  |  Branch (129:7): [True: 1.16M, False: 4.75M]
  ------------------
  130|  1.58M|      case TokenType::LessEqual:
  ------------------
  |  Branch (130:7): [True: 7.59k, False: 5.91M]
  ------------------
  131|  1.60M|      case TokenType::GreaterEqual:
  ------------------
  |  Branch (131:7): [True: 17.4k, False: 5.90M]
  ------------------
  132|  1.60M|        return kComparisonBP;
  133|       |      // Bitwise OR/XOR (level 6)
  134|   610k|      case TokenType::Pipe:
  ------------------
  |  Branch (134:7): [True: 610k, False: 5.31M]
  ------------------
  135|   611k|      case TokenType::Caret:
  ------------------
  |  Branch (135:7): [True: 1.19k, False: 5.92M]
  ------------------
  136|   611k|        return 12;
  137|       |      // Bitwise AND (level 7)
  138|  7.76k|      case TokenType::Ampersand:
  ------------------
  |  Branch (138:7): [True: 7.76k, False: 5.91M]
  ------------------
  139|  7.76k|        return 14;
  140|       |      // Add/Sub/Concat (level 8)
  141|  17.7k|      case TokenType::Plus:
  ------------------
  |  Branch (141:7): [True: 17.7k, False: 5.90M]
  ------------------
  142|  20.8k|      case TokenType::Minus:
  ------------------
  |  Branch (142:7): [True: 3.14k, False: 5.92M]
  ------------------
  143|  36.1k|      case TokenType::DotDot:
  ------------------
  |  Branch (143:7): [True: 15.2k, False: 5.91M]
  ------------------
  144|  36.1k|        return 16;
  145|       |      // Mul/Div (level 9)
  146|  1.24k|      case TokenType::Star:
  ------------------
  |  Branch (146:7): [True: 1.24k, False: 5.92M]
  ------------------
  147|  2.67k|      case TokenType::Slash:
  ------------------
  |  Branch (147:7): [True: 1.42k, False: 5.92M]
  ------------------
  148|  2.67k|        return kMulDivBP;
  149|  3.59M|      default:
  ------------------
  |  Branch (149:7): [True: 3.59M, False: 2.33M]
  ------------------
  150|  3.59M|        return -1;
  151|  5.92M|    }
  152|  5.92M|  }
_ZN2BT9Scripting12ScriptParser12isAssignmentENS0_9TokenTypeE:
  162|   453k|  {
  163|   453k|    return type == TokenType::ColonEqual || type == TokenType::Equal ||
  ------------------
  |  Branch (163:12): [True: 21.2k, False: 431k]
  |  Branch (163:45): [True: 12.0k, False: 419k]
  ------------------
  164|   419k|           type == TokenType::PlusEqual || type == TokenType::MinusEqual ||
  ------------------
  |  Branch (164:12): [True: 17.3k, False: 402k]
  |  Branch (164:44): [True: 1.67k, False: 400k]
  ------------------
  165|   400k|           type == TokenType::StarEqual || type == TokenType::SlashEqual;
  ------------------
  |  Branch (165:12): [True: 2.62k, False: 398k]
  |  Branch (165:44): [True: 1.60k, False: 396k]
  ------------------
  166|   453k|  }
_ZN2BT9Scripting12ScriptParser15parseAssignmentESt10shared_ptrINS_3Ast8ExprBaseEE:
  326|  56.5k|  {
  327|  56.5k|    const auto& opTok = advance();
  328|  56.5k|    Ast::ExprAssignment::op_t op{};
  329|  56.5k|    switch(opTok.type)
  330|  56.5k|    {
  331|  21.2k|      case TokenType::ColonEqual:
  ------------------
  |  Branch (331:7): [True: 21.2k, False: 35.2k]
  ------------------
  332|  21.2k|        op = Ast::ExprAssignment::assign_create;
  333|  21.2k|        break;
  334|  12.0k|      case TokenType::Equal:
  ------------------
  |  Branch (334:7): [True: 12.0k, False: 44.4k]
  ------------------
  335|  12.0k|        op = Ast::ExprAssignment::assign_existing;
  336|  12.0k|        break;
  337|  17.3k|      case TokenType::PlusEqual:
  ------------------
  |  Branch (337:7): [True: 17.3k, False: 39.1k]
  ------------------
  338|  17.3k|        op = Ast::ExprAssignment::assign_plus;
  339|  17.3k|        break;
  340|  1.67k|      case TokenType::MinusEqual:
  ------------------
  |  Branch (340:7): [True: 1.67k, False: 54.8k]
  ------------------
  341|  1.67k|        op = Ast::ExprAssignment::assign_minus;
  342|  1.67k|        break;
  343|  2.62k|      case TokenType::StarEqual:
  ------------------
  |  Branch (343:7): [True: 2.62k, False: 53.8k]
  ------------------
  344|  2.62k|        op = Ast::ExprAssignment::assign_times;
  345|  2.62k|        break;
  346|  1.60k|      case TokenType::SlashEqual:
  ------------------
  |  Branch (346:7): [True: 1.60k, False: 54.9k]
  ------------------
  347|  1.60k|        op = Ast::ExprAssignment::assign_div;
  348|  1.60k|        break;
  349|      0|      default:
  ------------------
  |  Branch (349:7): [True: 0, False: 56.5k]
  ------------------
  350|      0|        throw RuntimeError("Internal error: unexpected assignment op");
  351|  56.5k|    }
  352|       |    // Parse RHS -- use minBP=0 to allow full expression
  353|  56.5k|    auto right = parseExpr(0);
  354|  56.5k|    return std::make_shared<Ast::ExprAssignment>(std::move(left), op, std::move(right));
  355|  56.5k|  }
_ZN2BT9Scripting12ScriptParser12parseTernaryESt10shared_ptrINS_3Ast8ExprBaseEE:
  358|  7.39k|  {
  359|  7.39k|    advance();                     // consume '?'
  360|  7.39k|    auto thenExpr = parseExpr(0);  // full expression inside
  361|  7.39k|    expect(TokenType::Colon, "expected ':' in ternary expression");
  362|  7.39k|    auto elseExpr = parseExpr(kTernaryBP);
  363|  7.39k|    return std::make_shared<Ast::ExprIf>(std::move(condition), std::move(thenExpr),
  364|  7.39k|                                         std::move(elseExpr));
  365|  7.39k|  }
_ZN2BT9Scripting12ScriptParser12isComparisonENS0_9TokenTypeE:
  155|  2.03M|  {
  156|  2.03M|    return type == TokenType::EqualEqual || type == TokenType::BangEqual ||
  ------------------
  |  Branch (156:12): [True: 11.4k, False: 2.02M]
  |  Branch (156:45): [True: 45.3k, False: 1.98M]
  ------------------
  157|  1.98M|           type == TokenType::Less || type == TokenType::Greater ||
  ------------------
  |  Branch (157:12): [True: 368k, False: 1.61M]
  |  Branch (157:39): [True: 1.18M, False: 428k]
  ------------------
  158|   428k|           type == TokenType::LessEqual || type == TokenType::GreaterEqual;
  ------------------
  |  Branch (158:12): [True: 12.6k, False: 416k]
  |  Branch (158:44): [True: 29.4k, False: 386k]
  ------------------
  159|  2.03M|  }
_ZN2BT9Scripting12ScriptParser22parseChainedComparisonESt10shared_ptrINS_3Ast8ExprBaseEE:
  368|  51.0k|  {
  369|  51.0k|    auto node = std::make_shared<Ast::ExprComparison>();
  370|  51.0k|    node->operands.push_back(std::move(first));
  371|       |
  372|  1.65M|    while(isComparison(peek().type))
  ------------------
  |  Branch (372:11): [True: 1.59M, False: 51.0k]
  ------------------
  373|  1.59M|    {
  374|  1.59M|      node->ops.push_back(mapComparisonOp(advance().type));
  375|       |      // Parse the next operand above comparison level
  376|       |      // so that arithmetic binds tighter
  377|  1.59M|      node->operands.push_back(parseExpr(kComparisonBP + 1));
  378|  1.59M|    }
  379|  51.0k|    return node;
  380|  51.0k|  }
_ZN2BT9Scripting12ScriptParser15mapComparisonOpENS0_9TokenTypeE:
  383|  1.59M|  {
  384|  1.59M|    switch(type)
  385|  1.59M|    {
  386|  7.03k|      case TokenType::EqualEqual:
  ------------------
  |  Branch (386:7): [True: 7.03k, False: 1.59M]
  ------------------
  387|  7.03k|        return Ast::ExprComparison::equal;
  388|  40.6k|      case TokenType::BangEqual:
  ------------------
  |  Branch (388:7): [True: 40.6k, False: 1.55M]
  ------------------
  389|  40.6k|        return Ast::ExprComparison::not_equal;
  390|   358k|      case TokenType::Less:
  ------------------
  |  Branch (390:7): [True: 358k, False: 1.24M]
  ------------------
  391|   358k|        return Ast::ExprComparison::less;
  392|  1.16M|      case TokenType::Greater:
  ------------------
  |  Branch (392:7): [True: 1.16M, False: 429k]
  ------------------
  393|  1.16M|        return Ast::ExprComparison::greater;
  394|  7.38k|      case TokenType::LessEqual:
  ------------------
  |  Branch (394:7): [True: 7.38k, False: 1.59M]
  ------------------
  395|  7.38k|        return Ast::ExprComparison::less_equal;
  396|  16.1k|      case TokenType::GreaterEqual:
  ------------------
  |  Branch (396:7): [True: 16.1k, False: 1.58M]
  ------------------
  397|  16.1k|        return Ast::ExprComparison::greater_equal;
  398|      0|      default:
  ------------------
  |  Branch (398:7): [True: 0, False: 1.59M]
  ------------------
  399|      0|        throw RuntimeError("Internal error: not a comparison op");
  400|  1.59M|    }
  401|  1.59M|  }
_ZN2BT9Scripting12ScriptParser10makeBinaryESt10shared_ptrINS_3Ast8ExprBaseEENS0_9TokenTypeES5_:
  405|   336k|  {
  406|   336k|    Ast::ExprBinaryArithmetic::op_t op{};
  407|   336k|    switch(opType)
  408|   336k|    {
  409|  11.2k|      case TokenType::Plus:
  ------------------
  |  Branch (409:7): [True: 11.2k, False: 325k]
  ------------------
  410|  11.2k|        op = Ast::ExprBinaryArithmetic::plus;
  411|  11.2k|        break;
  412|  1.80k|      case TokenType::Minus:
  ------------------
  |  Branch (412:7): [True: 1.80k, False: 335k]
  ------------------
  413|  1.80k|        op = Ast::ExprBinaryArithmetic::minus;
  414|  1.80k|        break;
  415|    597|      case TokenType::Star:
  ------------------
  |  Branch (415:7): [True: 597, False: 336k]
  ------------------
  416|    597|        op = Ast::ExprBinaryArithmetic::times;
  417|    597|        break;
  418|    774|      case TokenType::Slash:
  ------------------
  |  Branch (418:7): [True: 774, False: 336k]
  ------------------
  419|    774|        op = Ast::ExprBinaryArithmetic::div;
  420|    774|        break;
  421|  10.0k|      case TokenType::DotDot:
  ------------------
  |  Branch (421:7): [True: 10.0k, False: 326k]
  ------------------
  422|  10.0k|        op = Ast::ExprBinaryArithmetic::concat;
  423|  10.0k|        break;
  424|  3.71k|      case TokenType::Ampersand:
  ------------------
  |  Branch (424:7): [True: 3.71k, False: 333k]
  ------------------
  425|  3.71k|        op = Ast::ExprBinaryArithmetic::bit_and;
  426|  3.71k|        break;
  427|   305k|      case TokenType::Pipe:
  ------------------
  |  Branch (427:7): [True: 305k, False: 31.5k]
  ------------------
  428|   305k|        op = Ast::ExprBinaryArithmetic::bit_or;
  429|   305k|        break;
  430|    630|      case TokenType::Caret:
  ------------------
  |  Branch (430:7): [True: 630, False: 336k]
  ------------------
  431|    630|        op = Ast::ExprBinaryArithmetic::bit_xor;
  432|    630|        break;
  433|  1.21k|      case TokenType::AmpAmp:
  ------------------
  |  Branch (433:7): [True: 1.21k, False: 335k]
  ------------------
  434|  1.21k|        op = Ast::ExprBinaryArithmetic::logic_and;
  435|  1.21k|        break;
  436|  1.39k|      case TokenType::PipePipe:
  ------------------
  |  Branch (436:7): [True: 1.39k, False: 335k]
  ------------------
  437|  1.39k|        op = Ast::ExprBinaryArithmetic::logic_or;
  438|  1.39k|        break;
  439|      0|      default:
  ------------------
  |  Branch (439:7): [True: 0, False: 336k]
  ------------------
  440|      0|        throw RuntimeError("Internal error: unknown binary operator");
  441|   336k|    }
  442|   336k|    return std::make_shared<Ast::ExprBinaryArithmetic>(std::move(left), op,
  443|   336k|                                                       std::move(right));
  444|   336k|  }
_ZNK2BT9Scripting12ScriptParser5checkENS0_9TokenTypeE:
   86|  3.52M|  {
   87|  3.52M|    return peek().type == type;
   88|  3.52M|  }
_ZN2BT9Scripting12ScriptParser7advanceEv:
   73|  7.57M|  {
   74|  7.57M|    const Token& tok = tokens_[current_];
   75|  7.57M|    if(!atEnd())
  ------------------
  |  Branch (75:8): [True: 7.57M, False: 0]
  ------------------
   76|  7.57M|      current_++;
   77|  7.57M|    return tok;
   78|  7.57M|  }
script_parser.cpp:_ZZN2BT11ParseScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENK3$_0clERNS_3Ast11EnvironmentE:
  467|  3.85k|    return [exprs = std::move(exprs), script](Ast::Environment& env) {
  468|  3.85k|      try
  469|  3.85k|      {
  470|  98.8k|        for(size_t i = 0; i < exprs.size() - 1; ++i)
  ------------------
  |  Branch (470:27): [True: 94.9k, False: 3.85k]
  ------------------
  471|  94.9k|        {
  472|  94.9k|          exprs[i]->evaluate(env);
  473|  94.9k|        }
  474|  3.85k|        return exprs.back()->evaluate(env);
  475|  3.85k|      }
  476|  3.85k|      catch(RuntimeError& err)
  477|  3.85k|      {
  478|    996|        throw RuntimeError(StrCat("Error in script [", script, "]\n", err.what()));
  479|    996|      }
  480|  3.85k|    };

_ZN2BT9Scripting8tokenizeERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  224|  12.3k|{
  225|  12.3k|  std::vector<Token> tokens;
  226|  12.3k|  const size_t len = source.size();
  227|  12.3k|  size_t i = 0;
  228|       |
  229|  38.4M|  while(i < len)
  ------------------
  |  Branch (229:9): [True: 38.4M, False: 12.3k]
  ------------------
  230|  38.4M|  {
  231|  38.4M|    const char c = source[i];
  232|       |
  233|       |    // Skip whitespace (space, tab, newline, carriage return)
  234|  38.4M|    if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
  ------------------
  |  Branch (234:8): [True: 9.46k, False: 38.4M]
  |  Branch (234:20): [True: 11.8k, False: 38.4M]
  |  Branch (234:33): [True: 267k, False: 38.1M]
  |  Branch (234:46): [True: 8.05k, False: 38.1M]
  ------------------
  235|   296k|    {
  236|   296k|      ++i;
  237|   296k|      continue;
  238|   296k|    }
  239|       |
  240|  38.1M|    const size_t start = i;
  241|       |
  242|       |    // Single-quoted string literal
  243|  38.1M|    if(c == '\'')
  ------------------
  |  Branch (243:8): [True: 453k, False: 37.7M]
  ------------------
  244|   453k|    {
  245|   453k|      ++i;
  246|  61.4M|      while(i < len && source[i] != '\'')
  ------------------
  |  Branch (246:13): [True: 61.4M, False: 363]
  |  Branch (246:24): [True: 61.0M, False: 453k]
  ------------------
  247|  61.0M|      {
  248|  61.0M|        ++i;
  249|  61.0M|      }
  250|   453k|      if(i < len)
  ------------------
  |  Branch (250:10): [True: 453k, False: 363]
  ------------------
  251|   453k|      {
  252|       |        // extract content without quotes
  253|   453k|        std::string_view text(&source[start + 1], i - start - 1);
  254|   453k|        tokens.push_back({ TokenType::String, text, start });
  255|   453k|        ++i;  // skip closing quote
  256|   453k|      }
  257|    363|      else
  258|    363|      {
  259|    363|        std::string_view text(&source[start], i - start);
  260|    363|        tokens.push_back({ TokenType::Error, text, start });
  261|    363|      }
  262|   453k|      continue;
  263|   453k|    }
  264|       |
  265|       |    // Number literal (integer or real)
  266|  37.7M|    if(isDigit(c))
  ------------------
  |  Branch (266:8): [True: 3.89M, False: 33.8M]
  ------------------
  267|  3.89M|    {
  268|  3.89M|      NumberResult nr;
  269|  3.89M|      const bool is_hex =
  270|  3.89M|          c == '0' && i + 1 < len && (source[i + 1] == 'x' || source[i + 1] == 'X');
  ------------------
  |  Branch (270:11): [True: 435k, False: 3.45M]
  |  Branch (270:23): [True: 434k, False: 701]
  |  Branch (270:39): [True: 61.3k, False: 373k]
  |  Branch (270:63): [True: 7.11k, False: 366k]
  ------------------
  271|  3.89M|      if(is_hex)
  ------------------
  |  Branch (271:10): [True: 68.5k, False: 3.82M]
  ------------------
  272|  68.5k|      {
  273|  68.5k|        nr = scanHexNumber(source, len, i);
  274|  68.5k|      }
  275|  3.82M|      else
  276|  3.82M|      {
  277|  3.82M|        nr = scanDecimalNumber(source, len, i);
  278|  3.82M|      }
  279|       |
  280|  3.89M|      std::string_view text(&source[start], i - start);
  281|  3.89M|      if(nr.has_error)
  ------------------
  |  Branch (281:10): [True: 394k, False: 3.49M]
  ------------------
  282|   394k|      {
  283|   394k|        tokens.push_back({ TokenType::Error, text, start });
  284|   394k|      }
  285|  3.49M|      else if(nr.is_real)
  ------------------
  |  Branch (285:15): [True: 69.4k, False: 3.42M]
  ------------------
  286|  69.4k|      {
  287|  69.4k|        tokens.push_back({ TokenType::Real, text, start });
  288|  69.4k|      }
  289|  3.42M|      else
  290|  3.42M|      {
  291|  3.42M|        tokens.push_back({ TokenType::Integer, text, start });
  292|  3.42M|      }
  293|  3.89M|      continue;
  294|  3.89M|    }
  295|       |
  296|       |    // Identifier or keyword (true/false)
  297|  33.8M|    if(isIdentStart(c))
  ------------------
  |  Branch (297:8): [True: 6.93M, False: 26.8M]
  ------------------
  298|  6.93M|    {
  299|  6.93M|      ++i;  // consume start character (may not be isIdentChar, e.g. '@')
  300|  60.7M|      while(i < len && isIdentChar(source[i]))
  ------------------
  |  Branch (300:13): [True: 60.7M, False: 2.95k]
  |  Branch (300:24): [True: 53.8M, False: 6.93M]
  ------------------
  301|  53.8M|      {
  302|  53.8M|        ++i;
  303|  53.8M|      }
  304|  6.93M|      if(std::string_view text(&source[start], i - start); text == "true" || text == "fal"
  ------------------
  |  Branch (304:60): [True: 5.35k, False: 6.92M]
  |  Branch (304:78): [True: 1.56k, False: 6.92M]
  ------------------
  305|  6.92M|                                                                                     "se")
  306|  6.92k|      {
  307|  6.92k|        tokens.push_back({ TokenType::Boolean, text, start });
  308|  6.92k|      }
  309|  6.92M|      else
  310|  6.92M|      {
  311|  6.92M|        tokens.push_back({ TokenType::Identifier, text, start });
  312|  6.92M|      }
  313|  6.93M|      continue;
  314|  6.93M|    }
  315|       |
  316|       |    // Two-character operators (check before single-char)
  317|  26.8M|    if(i + 1 < len)
  ------------------
  |  Branch (317:8): [True: 26.8M, False: 2.08k]
  ------------------
  318|  26.8M|    {
  319|  26.8M|      TokenType two_char_type = matchTwoCharOp(c, source[i + 1]);
  320|  26.8M|      if(two_char_type != TokenType::Error)
  ------------------
  |  Branch (320:10): [True: 269k, False: 26.6M]
  ------------------
  321|   269k|      {
  322|   269k|        std::string_view text(&source[start], 2);
  323|   269k|        tokens.push_back({ two_char_type, text, start });
  324|   269k|        i += 2;
  325|   269k|        continue;
  326|   269k|      }
  327|  26.8M|    }
  328|       |
  329|       |    // Single-character operators and delimiters
  330|  26.6M|    std::string_view text(&source[start], 1);
  331|  26.6M|    tokens.push_back({ matchSingleCharOp(c), text, start });
  332|  26.6M|    ++i;
  333|  26.6M|  }
  334|       |
  335|       |  // Sentinel
  336|  12.3k|  tokens.push_back({ TokenType::EndOfInput, {}, i });
  337|  12.3k|  return tokens;
  338|  12.3k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_17isDigitEc:
   34|   104M|{
   35|   104M|  return std::isdigit(static_cast<unsigned char>(c)) != 0;
   36|   104M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_113scanHexNumberERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   59|  68.5k|{
   60|  68.5k|  NumberResult result;
   61|  68.5k|  i += 2;  // skip "0x"/"0X"
   62|  68.5k|  if(i >= len || !isHexDigit(source[i]))
  ------------------
  |  Branch (62:6): [True: 36, False: 68.4k]
  |  Branch (62:18): [True: 42.3k, False: 26.0k]
  ------------------
   63|  42.4k|  {
   64|  42.4k|    result.has_error = true;
   65|  42.4k|  }
   66|  26.0k|  else
   67|  26.0k|  {
   68|   725k|    while(i < len && isHexDigit(source[i]))
  ------------------
  |  Branch (68:11): [True: 724k, False: 622]
  |  Branch (68:22): [True: 699k, False: 25.4k]
  ------------------
   69|   699k|    {
   70|   699k|      ++i;
   71|   699k|    }
   72|  26.0k|  }
   73|       |  // Hex numbers don't support dot or exponent
   74|  68.5k|  if(i < len && (source[i] == '.' || isIdentChar(source[i])))
  ------------------
  |  Branch (74:6): [True: 67.8k, False: 658]
  |  Branch (74:18): [True: 2.23k, False: 65.6k]
  |  Branch (74:38): [True: 34.4k, False: 31.1k]
  ------------------
   75|  36.6k|  {
   76|  36.6k|    result.has_error = true;
   77|  36.6k|    consumeTrailingGarbage(source, len, i);
   78|  36.6k|  }
   79|  68.5k|  return result;
   80|  68.5k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_110isHexDigitEc:
   39|   793k|{
   40|   793k|  return std::isxdigit(static_cast<unsigned char>(c)) != 0;
   41|   793k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_122consumeTrailingGarbageERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   45|  40.4k|{
   46|   442k|  while(i < len && (isIdentChar(source[i]) || source[i] == '.'))
  ------------------
  |  Branch (46:9): [True: 442k, False: 201]
  |  Branch (46:21): [True: 397k, False: 44.4k]
  |  Branch (46:47): [True: 4.16k, False: 40.2k]
  ------------------
   47|   401k|  {
   48|   401k|    ++i;
   49|   401k|  }
   50|  40.4k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_117scanDecimalNumberERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   83|  3.82M|{
   84|  3.82M|  NumberResult result;
   85|       |
   86|       |  // Integer part
   87|  56.8M|  while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (87:9): [True: 56.8M, False: 2.37k]
  |  Branch (87:20): [True: 53.0M, False: 3.81M]
  ------------------
   88|  53.0M|  {
   89|  53.0M|    ++i;
   90|  53.0M|  }
   91|       |  // Fractional part
   92|  3.82M|  if(i < len && source[i] == '.')
  ------------------
  |  Branch (92:6): [True: 3.81M, False: 2.37k]
  |  Branch (92:17): [True: 29.9k, False: 3.78M]
  ------------------
   93|  29.9k|  {
   94|       |    // Distinguish from ".." (concat operator)
   95|  29.9k|    if(i + 1 < len && source[i + 1] == '.')
  ------------------
  |  Branch (95:8): [True: 29.9k, False: 6]
  |  Branch (95:23): [True: 12.7k, False: 17.1k]
  ------------------
   96|  12.7k|    {
   97|       |      // Stop here: "65.." is Integer("65") + DotDot
   98|  12.7k|    }
   99|  17.2k|    else if(i + 1 < len && isDigit(source[i + 1]))
  ------------------
  |  Branch (99:13): [True: 17.1k, False: 6]
  |  Branch (99:28): [True: 13.3k, False: 3.81k]
  ------------------
  100|  13.3k|    {
  101|  13.3k|      result.is_real = true;
  102|  13.3k|      ++i;  // consume '.'
  103|  9.67M|      while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (103:13): [True: 9.67M, False: 83]
  |  Branch (103:24): [True: 9.66M, False: 13.2k]
  ------------------
  104|  9.66M|      {
  105|  9.66M|        ++i;
  106|  9.66M|      }
  107|  13.3k|    }
  108|  3.81k|    else
  109|  3.81k|    {
  110|       |      // "65." or "65.x" -- incomplete real
  111|  3.81k|      result.has_error = true;
  112|  3.81k|      ++i;  // consume the dot
  113|  3.81k|      consumeTrailingGarbage(source, len, i);
  114|  3.81k|    }
  115|  29.9k|  }
  116|       |  // Exponent (only for decimal numbers)
  117|  3.82M|  if(!result.has_error && i < len && (source[i] == 'e' || source[i] == 'E'))
  ------------------
  |  Branch (117:6): [True: 3.81M, False: 3.81k]
  |  Branch (117:27): [True: 3.81M, False: 2.45k]
  |  Branch (117:39): [True: 8.22k, False: 3.80M]
  |  Branch (117:59): [True: 57.0k, False: 3.75M]
  ------------------
  118|  65.2k|  {
  119|  65.2k|    result.is_real = true;
  120|  65.2k|    ++i;  // consume 'e'/'E'
  121|  65.2k|    if(i < len && (source[i] == '+' || source[i] == '-'))
  ------------------
  |  Branch (121:8): [True: 65.2k, False: 33]
  |  Branch (121:20): [True: 1.17k, False: 64.0k]
  |  Branch (121:40): [True: 800, False: 63.2k]
  ------------------
  122|  1.97k|    {
  123|  1.97k|      ++i;  // consume sign
  124|  1.97k|    }
  125|  65.2k|    if(i >= len || !isDigit(source[i]))
  ------------------
  |  Branch (125:8): [True: 72, False: 65.2k]
  |  Branch (125:20): [True: 7.78k, False: 57.4k]
  ------------------
  126|  7.86k|    {
  127|  7.86k|      result.has_error = true;
  128|  7.86k|    }
  129|  57.4k|    else
  130|  57.4k|    {
  131|   420k|      while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (131:13): [True: 420k, False: 250]
  |  Branch (131:24): [True: 363k, False: 57.1k]
  ------------------
  132|   363k|      {
  133|   363k|        ++i;
  134|   363k|      }
  135|  57.4k|    }
  136|  65.2k|  }
  137|       |  // Trailing alpha (e.g. "3foo", "65.43foo")
  138|  3.82M|  if(!result.has_error && i < len && isIdentStart(source[i]))
  ------------------
  |  Branch (138:6): [True: 3.81M, False: 11.6k]
  |  Branch (138:27): [True: 3.80M, False: 2.70k]
  |  Branch (138:38): [True: 334k, False: 3.47M]
  ------------------
  139|   334k|  {
  140|   334k|    result.has_error = true;
  141|  3.92M|    while(i < len && isIdentChar(source[i]))
  ------------------
  |  Branch (141:11): [True: 3.92M, False: 99]
  |  Branch (141:22): [True: 3.59M, False: 334k]
  ------------------
  142|  3.59M|    {
  143|  3.59M|      ++i;
  144|  3.59M|    }
  145|   334k|  }
  146|  3.82M|  return result;
  147|  3.82M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_112isIdentStartEc:
   24|  37.6M|{
   25|  37.6M|  return std::isalpha(static_cast<unsigned char>(c)) != 0 || c == '_' || c == '@';
  ------------------
  |  Branch (25:10): [True: 1.64M, False: 35.9M]
  |  Branch (25:62): [True: 36.9k, False: 35.9M]
  |  Branch (25:74): [True: 5.58M, False: 30.3M]
  ------------------
   26|  37.6M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_111isIdentCharEc:
   29|  65.1M|{
   30|  65.1M|  return std::isalnum(static_cast<unsigned char>(c)) != 0 || c == '_';
  ------------------
  |  Branch (30:10): [True: 57.7M, False: 7.42M]
  |  Branch (30:62): [True: 85.8k, False: 7.34M]
  ------------------
   31|  65.1M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_114matchTwoCharOpEcc:
  150|  26.8M|{
  151|  26.8M|  if(c == '.' && next == '.')
  ------------------
  |  Branch (151:6): [True: 67.8k, False: 26.8M]
  |  Branch (151:18): [True: 41.4k, False: 26.3k]
  ------------------
  152|  41.4k|    return TokenType::DotDot;
  153|  26.8M|  if(c == '&' && next == '&')
  ------------------
  |  Branch (153:6): [True: 34.5k, False: 26.8M]
  |  Branch (153:18): [True: 12.5k, False: 21.9k]
  ------------------
  154|  12.5k|    return TokenType::AmpAmp;
  155|  26.8M|  if(c == '|' && next == '|')
  ------------------
  |  Branch (155:6): [True: 320k, False: 26.5M]
  |  Branch (155:18): [True: 6.65k, False: 314k]
  ------------------
  156|  6.65k|    return TokenType::PipePipe;
  157|  26.8M|  if(c == '=' && next == '=')
  ------------------
  |  Branch (157:6): [True: 98.1k, False: 26.7M]
  |  Branch (157:18): [True: 13.6k, False: 84.4k]
  ------------------
  158|  13.6k|    return TokenType::EqualEqual;
  159|  26.8M|  if(c == '!' && next == '=')
  ------------------
  |  Branch (159:6): [True: 140k, False: 26.6M]
  |  Branch (159:18): [True: 69.5k, False: 71.2k]
  ------------------
  160|  69.5k|    return TokenType::BangEqual;
  161|  26.7M|  if(c == '<' && next == '=')
  ------------------
  |  Branch (161:6): [True: 418k, False: 26.3M]
  |  Branch (161:18): [True: 25.6k, False: 393k]
  ------------------
  162|  25.6k|    return TokenType::LessEqual;
  163|  26.7M|  if(c == '>' && next == '=')
  ------------------
  |  Branch (163:6): [True: 2.26M, False: 24.4M]
  |  Branch (163:18): [True: 30.2k, False: 2.23M]
  ------------------
  164|  30.2k|    return TokenType::GreaterEqual;
  165|  26.6M|  if(c == ':' && next == '=')
  ------------------
  |  Branch (165:6): [True: 65.7k, False: 26.6M]
  |  Branch (165:18): [True: 36.9k, False: 28.8k]
  ------------------
  166|  36.9k|    return TokenType::ColonEqual;
  167|  26.6M|  if(c == '+' && next == '=')
  ------------------
  |  Branch (167:6): [True: 47.0k, False: 26.6M]
  |  Branch (167:18): [True: 23.5k, False: 23.5k]
  ------------------
  168|  23.5k|    return TokenType::PlusEqual;
  169|  26.6M|  if(c == '-' && next == '=')
  ------------------
  |  Branch (169:6): [True: 152k, False: 26.4M]
  |  Branch (169:18): [True: 2.95k, False: 150k]
  ------------------
  170|  2.95k|    return TokenType::MinusEqual;
  171|  26.6M|  if(c == '*' && next == '=')
  ------------------
  |  Branch (171:6): [True: 17.0k, False: 26.6M]
  |  Branch (171:18): [True: 3.94k, False: 13.1k]
  ------------------
  172|  3.94k|    return TokenType::StarEqual;
  173|  26.6M|  if(c == '/' && next == '=')
  ------------------
  |  Branch (173:6): [True: 32.7k, False: 26.5M]
  |  Branch (173:18): [True: 2.36k, False: 30.3k]
  ------------------
  174|  2.36k|    return TokenType::SlashEqual;
  175|  26.6M|  return TokenType::Error;
  176|  26.6M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_117matchSingleCharOpEc:
  179|  26.6M|{
  180|  26.6M|  switch(c)
  181|  26.6M|  {
  182|  23.5k|    case '+':
  ------------------
  |  Branch (182:5): [True: 23.5k, False: 26.5M]
  ------------------
  183|  23.5k|      return TokenType::Plus;
  184|   150k|    case '-':
  ------------------
  |  Branch (184:5): [True: 150k, False: 26.4M]
  ------------------
  185|   150k|      return TokenType::Minus;
  186|  13.1k|    case '*':
  ------------------
  |  Branch (186:5): [True: 13.1k, False: 26.6M]
  ------------------
  187|  13.1k|      return TokenType::Star;
  188|  30.4k|    case '/':
  ------------------
  |  Branch (188:5): [True: 30.4k, False: 26.5M]
  ------------------
  189|  30.4k|      return TokenType::Slash;
  190|  22.0k|    case '&':
  ------------------
  |  Branch (190:5): [True: 22.0k, False: 26.5M]
  ------------------
  191|  22.0k|      return TokenType::Ampersand;
  192|   314k|    case '|':
  ------------------
  |  Branch (192:5): [True: 314k, False: 26.3M]
  ------------------
  193|   314k|      return TokenType::Pipe;
  194|  25.7k|    case '^':
  ------------------
  |  Branch (194:5): [True: 25.7k, False: 26.5M]
  ------------------
  195|  25.7k|      return TokenType::Caret;
  196|  60.8k|    case '~':
  ------------------
  |  Branch (196:5): [True: 60.8k, False: 26.5M]
  ------------------
  197|  60.8k|      return TokenType::Tilde;
  198|  71.3k|    case '!':
  ------------------
  |  Branch (198:5): [True: 71.3k, False: 26.5M]
  ------------------
  199|  71.3k|      return TokenType::Bang;
  200|   393k|    case '<':
  ------------------
  |  Branch (200:5): [True: 393k, False: 26.2M]
  ------------------
  201|   393k|      return TokenType::Less;
  202|  2.23M|    case '>':
  ------------------
  |  Branch (202:5): [True: 2.23M, False: 24.3M]
  ------------------
  203|  2.23M|      return TokenType::Greater;
  204|  84.5k|    case '=':
  ------------------
  |  Branch (204:5): [True: 84.5k, False: 26.5M]
  ------------------
  205|  84.5k|      return TokenType::Equal;
  206|  31.3k|    case '?':
  ------------------
  |  Branch (206:5): [True: 31.3k, False: 26.5M]
  ------------------
  207|  31.3k|      return TokenType::Question;
  208|  28.9k|    case ':':
  ------------------
  |  Branch (208:5): [True: 28.9k, False: 26.5M]
  ------------------
  209|  28.9k|      return TokenType::Colon;
  210|  97.4k|    case '(':
  ------------------
  |  Branch (210:5): [True: 97.4k, False: 26.5M]
  ------------------
  211|  97.4k|      return TokenType::LeftParen;
  212|  7.99k|    case ')':
  ------------------
  |  Branch (212:5): [True: 7.99k, False: 26.6M]
  ------------------
  213|  7.99k|      return TokenType::RightParen;
  214|  94.3k|    case ';':
  ------------------
  |  Branch (214:5): [True: 94.3k, False: 26.5M]
  ------------------
  215|  94.3k|      return TokenType::Semicolon;
  216|  22.9M|    default:
  ------------------
  |  Branch (216:5): [True: 22.9M, False: 3.68M]
  ------------------
  217|  22.9M|      return TokenType::Error;
  218|  26.6M|  }
  219|  26.6M|}

