1896:                                            local.addr_strings.push_back({housenumber, street});
2110:                                                local.addr_strings.push_back(std::string(housenumber) + "\0" + std::string(street));
2254:                        auto& s = local.addr_strings[i];
2256:                        std::string hn = s.substr(0, sep);
2257:                        std::string st = s.substr(sep + 1);


  2107→                                                    0, 0 // placeholder string IDs
  2108→                                                });
  2109→                                                // Store strings for later interning
  2110→                                                local.addr_strings.push_back(std::string(housenumber) + "\0" + std::string(street));
  2111→                                                local.building_addr_count++;

                                                    0, 0 // placeholder string IDs
                                                });
                                                // Store strings for later interning
                                                local.addr_strings.push_back(std::string(housenumber) + "\0" + std::string(street));
                                                local.building_addr_count++;


The issue is on line 2110: `std::string(housenumber) + "\0" + std::string(street)`. The `"\0"` is a C string literal which is effectively an empty string when used with `operator+` on std::string — the `+` concatenation stops at the null byte! So instead of embedding a null separator, it just concatenates housenumber+street directly.


  2249→                        data.deferred_ways.push_back(dw);
  2250→                    }
  2251→
  2252→                    // Merge building addresses
  2253→                    for (size_t i = 0; i < local.building_addrs.size(); i++) {
  2254→                        auto& s = local.addr_strings[i];
  2255→                        auto sep = s.find('\0');
  2256→                        std::string hn = s.substr(0, sep);
  2257→                        std::string st = s.substr(sep + 1);
  2258→                        uint64_t dummy = 0;
  2259→                        add_addr_point(data, local.building_addrs[i].lat, local.building_addrs[i].lng,
  2260→                                       hn.c_str(), st.c_str(), dummy);
  2261→                    }
  2262→
  2263→                    // Merge interpolation ways

                        data.deferred_ways.push_back(dw);
                    }

                    // Merge building addresses
                    for (size_t i = 0; i < local.building_addrs.size(); i++) {
                        auto& s = local.addr_strings[i];
                        auto sep = s.find('\0');
                        std::string hn = s.substr(0, sep);
                        std::string st = s.substr(sep + 1);
                        uint64_t dummy = 0;
                        add_addr_point(data, local.building_addrs[i].lat, local.building_addrs[i].lng,
                                       hn.c_str(), st.c_str(), dummy);
                    }

                    // Merge interpolation ways


The problem is clear: `std::string(housenumber) + "\0"` creates `std::string(housenumber) + std::string("")` because `"\0"` is a C-string with just a null terminator — it's an empty string. The null byte never gets embedded.

Then `s.find('\0')` returns `std::string::npos` (not found), so `s.substr(0, npos)` returns the entire string, and `s.substr(npos + 1)` wraps around and also returns the whole string. Both hn and st end up being the full concatenated string.

The fix: use a `std::pair<std::string, std::string>` instead of the embedded-null hack, just like the node address code does.


Edit

std::vector<std::string> addr_strings;     // building addr "hn\0street" strings

std::vector<std::pair<std::string,std::string>> addr_strings; // building addr {hn, street}