Jan 06 2026 dev (#387)

* sync code

* update code to support brotli

* update code to support brotli

* update code to support brotli

* sync code

* fix findBrotli

* sync code

* sync code

* sync code

* sync code

---------

Co-authored-by: Ned Wright <nedwright@proton.me>
Co-authored-by: Daniel Eisenberg <danielei@checkpoint.com>
This commit is contained in:
Daniel-Eisenberg
2026-01-13 17:17:52 +02:00
committed by GitHub
parent c1058db57d
commit e7b6e51b31
216 changed files with 12601 additions and 2825 deletions

View File

@@ -20,56 +20,131 @@
USE_DEBUG_FLAG(D_WAAP);
KeyStack::KeyStack(const char* name)
:m_name(name), m_nameDepth(0) {
:m_name(name), m_nameDepth(0), m_total_length(0), m_using_buffer(true),
m_str_cache_valid(false), m_first_cache_valid(false) {
m_buffer[0] = '\0';
m_positions.reserve(16); // Reserve reasonable capacity
m_lengths.reserve(16);
m_fallback_stack.reserve(16);
}
void KeyStack::push(const char* subkey, size_t subkeySize, bool countDepth) {
m_stack.push_back(m_key.size());
void
KeyStack::push(const char *subkey, size_t subkeySize, bool countDepth)
{
bool dot_needed = !m_positions.empty() && subkey != nullptr && subkeySize > 0;
if (m_using_buffer) {
// Calculate space needed: subkey + dot (if not first) + null terminator
size_t dot_size = dot_needed ? 1 : 0;
size_t needed_space = subkeySize + dot_size + 1; // +1 for null terminator
// Prefix all subkeys (except the first) with '.'
if (!m_key.empty()) {
m_key += '.';
if (can_fit_in_buffer(needed_space)) {
// Fast path: use fixed buffer
if (dot_needed) {
m_buffer[m_total_length] = '.';
m_total_length++;
}
m_positions.push_back(m_total_length);
m_lengths.push_back(subkeySize);
memcpy(m_buffer + m_total_length, subkey, subkeySize);
m_total_length += subkeySize;
m_buffer[m_total_length] = '\0';
} else {
// Switch to fallback mode
switch_to_fallback();
// Continue with fallback logic below
}
}
m_key += std::string(subkey, subkeySize);
if (!m_using_buffer) {
// Slow path: use dynamic string
m_fallback_stack.push_back(m_fallback_key.size());
if (dot_needed) {
m_fallback_key.append(1, '.');
}
m_fallback_key.append(subkey, subkeySize);
}
if (countDepth) {
m_nameDepth++;
}
// Invalidate cache since key structure changed
invalidate_cache();
dbgTrace(D_WAAP)
<< "KeyStack("
<< m_name
<< ")::push(): '"
<< std::string(subkey, subkeySize)
<< "' => full_key='"
<< std::string(m_key.data(), m_key.size())
<< c_str()
<< "'";
}
void KeyStack::pop(const char* log, bool countDepth) {
// Keep depth balanced even if m_key[] buffer is full
if (m_key.empty() || m_stack.empty()) {
dbgDebug(D_WAAP)
<< "KeyStack("
<< m_name
<< ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! "
<< log;
return;
if (m_using_buffer) {
if (m_positions.empty()) {
dbgDebug(D_WAAP)
<< "KeyStack("
<< m_name
<< ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! "
<< log;
return;
}
// Remove last subkey from buffer
m_total_length = m_positions.back();
// Only remove dot if:
// 1. There are multiple elements (not the first)
// 2. The element being popped had content (length > 0, meaning a dot was added)
// 3. The character before current position is actually a dot (safety check)
if (m_positions.size() > 1 && m_lengths.back() > 0) {
if (m_total_length > 0 && m_buffer[m_total_length - 1] == '.') {
m_total_length -= 1; // Remove the dot
}
} else if (m_positions.size() == 1) {
m_total_length = 0; // First element, no dot to remove
}
m_positions.pop_back();
m_lengths.pop_back();
m_buffer[m_total_length] = '\0';
} else {
// Fallback mode
if (m_fallback_key.empty() || m_fallback_stack.empty()) {
dbgDebug(D_WAAP)
<< "KeyStack("
<< m_name
<< ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! "
<< log;
return;
}
// Remove last subkey
m_fallback_key.erase(m_fallback_stack.back());
m_fallback_stack.pop_back();
// Try to switch back to buffer if possible
if (m_fallback_key.size() + 1 < MAX_KEY_SIZE) {
rebuild_buffer_from_fallback();
}
}
if (countDepth) {
m_nameDepth--;
}
// Remove last subkey.
m_key.erase(m_stack.back());
m_stack.pop_back();
// Invalidate cache since key structure changed
invalidate_cache();
dbgTrace(D_WAAP)
<< "KeyStack("
<< m_name
<< ")::pop(): full_key='"
<< std::string(m_key.data(), (int)m_key.size())
<< c_str()
<< "': pop_key="
<< log
<< "'";
@@ -81,6 +156,200 @@ void KeyStack::print(std::ostream &os) const
<< "KeyStack("
<< m_name
<< ")::show(): full_key='"
<< std::string(m_key.data(), (int)m_key.size())
<< c_str()
<< "'";
}
void KeyStack::clear() {
if (m_using_buffer) {
m_positions.clear();
m_lengths.clear();
m_total_length = 0;
m_buffer[0] = '\0';
} else {
m_fallback_key.clear();
m_fallback_stack.clear();
m_using_buffer = true;
m_total_length = 0;
m_buffer[0] = '\0';
}
m_nameDepth = 0;
invalidate_cache();
}
size_t KeyStack::size() const {
if (m_using_buffer) {
if (m_positions.size() <= 1 || m_positions[1] >= m_total_length) {
// No second element or second element has no content
return 0;
}
// Return size from second subkey onwards
return m_total_length - m_positions[1];
} else {
// Fallback mode
if (m_fallback_stack.size() <= 1) {
return 0;
}
// m_fallback_stack[1] points to the dot preceding the 2nd subkey.
// Exclude the dot itself from the reported size.
if (m_fallback_stack[1] + 1 >= m_fallback_key.size()) {
return 0; // Defensive: nothing after the dot
}
return m_fallback_key.size() - (m_fallback_stack[1] + 1);
}
}
const char* KeyStack::c_str() const {
if (m_using_buffer) {
if (m_positions.size() <= 1 || m_positions[1] >= m_total_length) {
// No second element or second element has no content
return "";
}
// Return pointer to second subkey (skip first + dot)
return m_buffer + m_positions[1];
} else {
// Fallback mode
if (m_fallback_stack.size() <= 1) {
return "";
}
// m_fallback_stack[1] points to the dot. Skip it for consistency with buffer mode.
static thread_local std::string temp_result;
size_t start = m_fallback_stack[1] + 1;
if (start >= m_fallback_key.size()) {
temp_result.clear();
} else {
temp_result = m_fallback_key.substr(start);
}
return temp_result.c_str();
}
}
const std::string KeyStack::str() const {
if (m_str_cache_valid) {
return m_cached_str;
}
if (m_using_buffer) {
if (m_positions.size() <= 1 || m_positions[1] >= m_total_length) {
// No second element or second element has no content
m_cached_str = std::string();
} else {
// Return string from second subkey onwards
m_cached_str = std::string(m_buffer + m_positions[1], m_total_length - m_positions[1]);
}
} else {
// Fallback mode
if (m_fallback_stack.size() <= 1) {
m_cached_str = std::string();
} else {
size_t start = m_fallback_stack[1] + 1; // Skip the dot
if (start >= m_fallback_key.size()) {
m_cached_str.clear();
} else {
m_cached_str = m_fallback_key.substr(start);
}
}
}
m_str_cache_valid = true;
return m_cached_str;
}
const std::string KeyStack::first() const {
if (m_first_cache_valid) {
return m_cached_first;
}
if (m_using_buffer) {
if (m_positions.empty()) {
m_cached_first = std::string();
} else if (m_positions.size() == 1) {
// Only one subkey, return the whole buffer content
m_cached_first = std::string(m_buffer, m_lengths[0]);
} else {
// Multiple subkeys, return first one
m_cached_first = std::string(m_buffer + m_positions[0], m_lengths[0]);
}
} else {
// Fallback mode
if (m_fallback_stack.empty()) {
m_cached_first = std::string();
} else if (m_fallback_stack.size() == 1) {
m_cached_first = m_fallback_key;
} else {
// m_fallback_stack[1] points to the dot; substring up to dot (exclude it)
size_t dot_pos = m_fallback_stack[1];
if (dot_pos == 0 || dot_pos > m_fallback_key.size()) {
m_cached_first.clear();
} else {
m_cached_first = m_fallback_key.substr(0, dot_pos);
}
}
}
m_first_cache_valid = true;
return m_cached_first;
}
bool KeyStack::can_fit_in_buffer(size_t additional_size) const {
return (m_total_length + additional_size) < MAX_KEY_SIZE;
}
void KeyStack::switch_to_fallback() {
// Copy buffer content to fallback string
m_fallback_key.assign(m_buffer, m_total_length);
// Convert positions to stack format used by fallback
m_fallback_stack.clear();
for (size_t i = 0; i < m_positions.size(); ++i) {
if (i == 0) {
m_fallback_stack.push_back(0);
} else {
// Position after dot
m_fallback_stack.push_back(m_positions[i] - 1);
}
}
m_using_buffer = false;
invalidate_cache();
}void KeyStack::rebuild_buffer_from_fallback() {
if (m_fallback_key.size() + 1 >= MAX_KEY_SIZE) {
return; // Still too big for buffer
}
// Copy fallback content back to buffer
memcpy(m_buffer, m_fallback_key.c_str(), m_fallback_key.size());
m_total_length = m_fallback_key.size();
m_buffer[m_total_length] = '\0';
// Rebuild positions and lengths by parsing the buffer
m_positions.clear();
m_lengths.clear();
size_t pos = 0;
while (pos < m_total_length) {
m_positions.push_back(pos);
// Find length of current subkey
size_t start = pos;
while (pos < m_total_length && m_buffer[pos] != '.') {
pos++;
}
m_lengths.push_back(pos - start);
if (pos < m_total_length) {
pos++; // Skip the dot
}
}
// Clear fallback data
m_fallback_key.clear();
m_fallback_stack.clear();
m_using_buffer = true;
invalidate_cache();
}
void KeyStack::invalidate_cache() {
m_str_cache_valid = false;
m_first_cache_valid = false;
}