Skip to content

Commit a26b709

Browse files
committed
Optimize string handling by migrating message constants and parser interface methods to std::string_view
1 parent 86febac commit a26b709

10 files changed

Lines changed: 92 additions & 75 deletions

File tree

agent_sdks/cpp/include/a2ui/parser/constants.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,24 @@
1616

1717
#pragma once
1818

19-
#include <string>
19+
#include <string_view>
2020

2121
namespace a2ui {
2222

23-
const std::string DEFAULT_ROOT_ID = "root";
23+
inline constexpr std::string_view DEFAULT_ROOT_ID = "root";
2424

2525
// Message types (v0.8)
26-
const std::string MSG_TYPE_BEGIN_RENDERING = "beginRendering";
27-
const std::string MSG_TYPE_SURFACE_UPDATE = "surfaceUpdate";
28-
const std::string MSG_TYPE_DATA_MODEL_UPDATE = "dataModelUpdate";
29-
const std::string MSG_TYPE_DELETE_SURFACE = "deleteSurface";
26+
inline constexpr std::string_view MSG_TYPE_BEGIN_RENDERING = "beginRendering";
27+
inline constexpr std::string_view MSG_TYPE_SURFACE_UPDATE = "surfaceUpdate";
28+
inline constexpr std::string_view MSG_TYPE_DATA_MODEL_UPDATE = "dataModelUpdate";
29+
inline constexpr std::string_view MSG_TYPE_DELETE_SURFACE = "deleteSurface";
3030

3131
// Message types (v0.9)
32-
const std::string MSG_TYPE_CREATE_SURFACE = "createSurface";
33-
const std::string MSG_TYPE_UPDATE_COMPONENTS = "updateComponents";
34-
const std::string MSG_TYPE_UPDATE_DATA_MODEL = "updateDataModel";
32+
inline constexpr std::string_view MSG_TYPE_CREATE_SURFACE = "createSurface";
33+
inline constexpr std::string_view MSG_TYPE_UPDATE_COMPONENTS = "updateComponents";
34+
inline constexpr std::string_view MSG_TYPE_UPDATE_DATA_MODEL = "updateDataModel";
3535

3636
// Conversational text (non-A2UI)
37-
const std::string MSG_TYPE_TEXT = "text";
37+
inline constexpr std::string_view MSG_TYPE_TEXT = "text";
3838

3939
} // namespace a2ui

agent_sdks/cpp/include/a2ui/parser/streaming.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "a2ui/schema/catalog.h"
2020
#include <string>
21+
#include <string_view>
2122
#include <vector>
2223
#include <optional>
2324
#include <nlohmann/json.hpp>
@@ -31,8 +32,8 @@ class A2uiStreamParser {
3132
virtual ~A2uiStreamParser() = default;
3233
virtual std::vector<ResponsePart> process_chunk(const std::string& chunk) = 0;
3334

34-
virtual std::string get_active_msg_type_for_components() const = 0;
35-
virtual std::string get_data_model_msg_type() const = 0;
35+
virtual std::string_view get_active_msg_type_for_components() const = 0;
36+
virtual std::string_view get_data_model_msg_type() const = 0;
3637
virtual bool deduplicate_data_model(const nlohmann::json& m, bool strict_integrity) = 0;
3738

3839
// Factory function

agent_sdks/cpp/include/a2ui/schema/constants.h

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,35 @@
1616

1717
#pragma once
1818

19-
#include <string>
19+
#include <string_view>
2020
#include <map>
2121

2222
namespace a2ui {
2323

24-
const std::string SERVER_TO_CLIENT_SCHEMA_KEY = "server_to_client";
25-
const std::string COMMON_TYPES_SCHEMA_KEY = "common_types";
26-
const std::string CATALOG_SCHEMA_KEY = "catalog";
27-
const std::string CATALOG_COMPONENTS_KEY = "components";
28-
const std::string CATALOG_ID_KEY = "catalogId";
29-
const std::string CATALOG_STYLES_KEY = "styles";
30-
const std::string SURFACE_ID_KEY = "surfaceId";
24+
inline constexpr std::string_view SERVER_TO_CLIENT_SCHEMA_KEY = "server_to_client";
25+
inline constexpr std::string_view COMMON_TYPES_SCHEMA_KEY = "common_types";
26+
inline constexpr std::string_view CATALOG_SCHEMA_KEY = "catalog";
27+
inline constexpr std::string_view CATALOG_COMPONENTS_KEY = "components";
28+
inline constexpr std::string_view CATALOG_ID_KEY = "catalogId";
29+
inline constexpr std::string_view CATALOG_STYLES_KEY = "styles";
30+
inline constexpr std::string_view SURFACE_ID_KEY = "surfaceId";
3131

32-
const std::string SUPPORTED_CATALOG_IDS_KEY = "supportedCatalogIds";
33-
const std::string INLINE_CATALOGS_KEY = "inlineCatalogs";
34-
const std::string A2UI_CLIENT_CAPABILITIES_KEY = "a2uiClientCapabilities";
35-
const std::string BASE_SCHEMA_URL = "https://a2ui.org/";
36-
const std::string INLINE_CATALOG_NAME = "inline";
32+
inline constexpr std::string_view SUPPORTED_CATALOG_IDS_KEY = "supportedCatalogIds";
33+
inline constexpr std::string_view INLINE_CATALOGS_KEY = "inlineCatalogs";
34+
inline constexpr std::string_view A2UI_CLIENT_CAPABILITIES_KEY = "a2uiClientCapabilities";
35+
inline constexpr std::string_view BASE_SCHEMA_URL = "https://a2ui.org/";
36+
inline constexpr std::string_view INLINE_CATALOG_NAME = "inline";
3737

38-
const std::string VERSION_0_8 = "0.8";
39-
const std::string VERSION_0_9 = "0.9";
38+
inline constexpr std::string_view VERSION_0_8 = "0.8";
39+
inline constexpr std::string_view VERSION_0_9 = "0.9";
4040

41-
const std::string A2UI_OPEN_TAG = "<a2ui-json>";
42-
const std::string A2UI_CLOSE_TAG = "</a2ui-json>";
41+
inline constexpr std::string_view A2UI_OPEN_TAG = "<a2ui-json>";
42+
inline constexpr std::string_view A2UI_CLOSE_TAG = "</a2ui-json>";
4343

44-
const std::string A2UI_SCHEMA_BLOCK_START = "---BEGIN A2UI JSON SCHEMA---";
45-
const std::string A2UI_SCHEMA_BLOCK_END = "---END A2UI JSON SCHEMA---";
44+
inline constexpr std::string_view A2UI_SCHEMA_BLOCK_START = "---BEGIN A2UI JSON SCHEMA---";
45+
inline constexpr std::string_view A2UI_SCHEMA_BLOCK_END = "---END A2UI JSON SCHEMA---";
4646

47-
const std::string DEFAULT_WORKFLOW_RULES = R"(
47+
inline constexpr std::string_view DEFAULT_WORKFLOW_RULES = R"(
4848
The generated response MUST follow these rules:
4949
- The response can contain one or more A2UI JSON blocks.
5050
- Each A2UI JSON block MUST be wrapped in <a2ui-json> and </a2ui-json> tags.

agent_sdks/cpp/src/parser/parser.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static std::string sanitize_json_string(const std::string& json_string) {
7272
std::vector<ResponsePart> parse_response(const std::string& content) {
7373
std::vector<ResponsePart> response_parts;
7474

75-
std::regex pattern_dotall(A2UI_OPEN_TAG + "([\\s\\S]*?)" + A2UI_CLOSE_TAG);
75+
static const std::regex pattern_dotall(std::string(A2UI_OPEN_TAG) + "([\\s\\S]*?)" + std::string(A2UI_CLOSE_TAG));
7676

7777
auto words_begin = std::sregex_iterator(content.begin(), content.end(), pattern_dotall);
7878
auto words_end = std::sregex_iterator();

agent_sdks/cpp/src/parser/streaming.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ std::string fix_json(const std::string& json_str) {
9898

9999
size_t lookback_start = (prefix.length() > 200) ? prefix.length() - 200 : 0;
100100
std::string lookback_str = prefix.substr(lookback_start);
101-
std::regex key_pattern(R"(\"key\"\s*:\s*\"([^\"]+)\")");
101+
static const std::regex key_pattern(R"(\"key\"\s*:\s*\"([^\"]+)\")");
102102
std::smatch match;
103103
std::string data_key = "";
104104
auto words_begin = std::sregex_iterator(lookback_str.begin(), lookback_str.end(), key_pattern);

agent_sdks/cpp/src/parser/streaming_impl.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class A2uiStreamParserImpl : public A2uiStreamParser {
178178
for (const auto& m : *part.a2ui_json) {
179179
bool is_su = false;
180180
std::string sid;
181-
std::string su_key = get_active_msg_type_for_components();
181+
std::string_view su_key = get_active_msg_type_for_components();
182182

183183
if (m.is_object() && m.contains(su_key)) {
184184
is_su = true;
@@ -343,7 +343,7 @@ class A2uiStreamParserImpl : public A2uiStreamParser {
343343
virtual bool handle_complete_object(const nlohmann::json& obj, const std::string& surface_id, std::vector<ResponsePart>& messages) = 0;
344344
virtual nlohmann::json create_placeholder_component(const std::string& id) const = 0;
345345
virtual bool is_protocol_msg(const nlohmann::json& obj) const = 0;
346-
virtual std::string get_active_msg_type_for_components() const = 0;
346+
virtual std::string_view get_active_msg_type_for_components() const = 0;
347347
virtual bool deduplicate_data_model(const nlohmann::json& m, bool strict_integrity) { return true; }
348348

349349
void sniff_partial_component(std::vector<ResponsePart>& messages) {
@@ -432,8 +432,9 @@ class A2uiStreamParserImpl : public A2uiStreamParser {
432432

433433
void sniff_partial_data_model(std::vector<ResponsePart>& messages) {
434434

435-
std::string msg_type = get_data_model_msg_type();
436-
if (json_buffer_.find("\"" + msg_type + "\"") == std::string::npos) {
435+
std::string_view msg_type = get_data_model_msg_type();
436+
std::string search_pattern = "\"" + std::string(msg_type) + "\"";
437+
if (json_buffer_.find(search_pattern) == std::string::npos) {
437438
return;
438439
}
439440

@@ -600,8 +601,8 @@ class A2uiStreamParserImpl : public A2uiStreamParser {
600601
topology_dirty_ = true;
601602
}
602603

603-
void yield_reachable(std::vector<ResponsePart>& messages, const std::string& msg_type = "", bool check_root = false, bool raise_on_orphans = false) {
604-
std::string active_msg_type = msg_type;
604+
void yield_reachable(std::vector<ResponsePart>& messages, std::string_view msg_type = "", bool check_root = false, bool raise_on_orphans = false) {
605+
std::string_view active_msg_type = msg_type;
605606
if (active_msg_type.empty()) active_msg_type = get_active_msg_type_for_components();
606607
if (surface_id_.empty() || active_msg_type.empty()) return;
607608

agent_sdks/cpp/src/parser/streaming_v08.h

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,36 @@ class A2uiStreamParserV08 : public A2uiStreamParserImpl {
3131

3232
protected:
3333
void sniff_metadata() override {
34-
// Simplified regex-based sniffing
35-
auto get_latest_value = [this](const std::string& key) -> std::string {
36-
std::regex pattern(R"(\")" + key + R"(\"\s*:\s*\"([^\"]+)\")");
37-
std::smatch match;
38-
std::string search_str = json_buffer_;
39-
std::string result = "";
40-
while (std::regex_search(search_str, match, pattern)) {
41-
result = match[1].str();
42-
search_str = match.suffix().str();
34+
static const std::regex sid_pattern(R"(\"surfaceId\"\s*:\s*\"([^\"]+)\")");
35+
static const std::regex root_pattern(R"(\"root\"\s*:\s*\"([^\"]+)\")");
36+
37+
auto get_latest_value = [this](std::string_view key, const std::regex& pattern) -> std::string_view {
38+
std::string pattern_str = "\"" + std::string(key) + "\"";
39+
size_t pos = json_buffer_.rfind(pattern_str);
40+
while (pos != std::string::npos) {
41+
std::smatch match;
42+
auto start = json_buffer_.cbegin() + pos;
43+
auto end = json_buffer_.cend();
44+
if (std::regex_search(start, end, match, pattern)) {
45+
return std::string_view(json_buffer_.data() + pos + match.position(1), match.length(1));
46+
}
47+
if (pos == 0) break;
48+
pos = json_buffer_.rfind(pattern_str, pos - 1);
4349
}
44-
return result;
50+
return "";
4551
};
4652

47-
std::string sid = get_latest_value("surfaceId");
53+
std::string_view sid = get_latest_value("surfaceId", sid_pattern);
4854
if (!sid.empty()) surface_id_ = sid;
4955

50-
std::string rid = get_latest_value("root");
56+
std::string_view rid = get_latest_value("root", root_pattern);
5157
if (!rid.empty()) root_ids_[surface_id_] = rid;
5258

53-
auto check_msg_type = [this](const std::string& type) {
54-
if (json_buffer_.find("\"" + type + "\":") != std::string::npos) {
59+
auto check_msg_type = [this](std::string_view type) {
60+
std::string search_str = "\"" + std::string(type) + "\":";
61+
if (json_buffer_.find(search_str) != std::string::npos) {
5562
if (std::find(msg_types_.begin(), msg_types_.end(), type) == msg_types_.end()) {
56-
msg_types_.push_back(type);
63+
msg_types_.push_back(std::string(type));
5764
}
5865
active_msg_type_ = type;
5966
}
@@ -164,11 +171,11 @@ class A2uiStreamParserV08 : public A2uiStreamParserImpl {
164171
return obj.contains(MSG_TYPE_BEGIN_RENDERING) || obj.contains(MSG_TYPE_SURFACE_UPDATE) || obj.contains(MSG_TYPE_DATA_MODEL_UPDATE) || obj.contains(MSG_TYPE_DELETE_SURFACE);
165172
}
166173

167-
std::string get_active_msg_type_for_components() const override {
174+
std::string_view get_active_msg_type_for_components() const override {
168175
return MSG_TYPE_SURFACE_UPDATE;
169176
}
170177

171-
std::string get_data_model_msg_type() const override {
178+
std::string_view get_data_model_msg_type() const override {
172179
return MSG_TYPE_DATA_MODEL_UPDATE;
173180
}
174181

agent_sdks/cpp/src/parser/streaming_v09.h

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,36 @@ class A2uiStreamParserV09 : public A2uiStreamParserImpl {
3333

3434
protected:
3535
void sniff_metadata() override {
36-
auto get_latest_value = [this](const std::string& key) -> std::string {
37-
std::regex pattern(R"(\")" + key + R"(\"\s*:\s*\"([^\"]+)\")");
38-
std::smatch match;
39-
std::string search_str = json_buffer_;
40-
std::string result = "";
41-
while (std::regex_search(search_str, match, pattern)) {
42-
result = match[1].str();
43-
search_str = match.suffix().str();
36+
static const std::regex sid_pattern(R"(\"surfaceId\"\s*:\s*\"([^\"]+)\")");
37+
static const std::regex root_pattern(R"(\"root\"\s*:\s*\"([^\"]+)\")");
38+
39+
auto get_latest_value = [this](std::string_view key, const std::regex& pattern) -> std::string_view {
40+
std::string pattern_str = "\"" + std::string(key) + "\"";
41+
size_t pos = json_buffer_.rfind(pattern_str);
42+
while (pos != std::string::npos) {
43+
std::smatch match;
44+
auto start = json_buffer_.cbegin() + pos;
45+
auto end = json_buffer_.cend();
46+
if (std::regex_search(start, end, match, pattern)) {
47+
return std::string_view(json_buffer_.data() + pos + match.position(1), match.length(1));
48+
}
49+
if (pos == 0) break;
50+
pos = json_buffer_.rfind(pattern_str, pos - 1);
4451
}
45-
return result;
52+
return "";
4653
};
4754

48-
std::string sid = get_latest_value("surfaceId");
55+
std::string_view sid = get_latest_value("surfaceId", sid_pattern);
4956
if (!sid.empty()) surface_id_ = sid;
5057

51-
std::string rid = get_latest_value("root");
58+
std::string_view rid = get_latest_value("root", root_pattern);
5259
if (!rid.empty()) root_ids_[surface_id_] = rid;
5360

54-
auto check_msg_type = [this](const std::string& type) {
55-
if (json_buffer_.find("\"" + type + "\":") != std::string::npos) {
61+
auto check_msg_type = [this](std::string_view type) {
62+
std::string search_str = "\"" + std::string(type) + "\":";
63+
if (json_buffer_.find(search_str) != std::string::npos) {
5664
if (std::find(msg_types_.begin(), msg_types_.end(), type) == msg_types_.end()) {
57-
msg_types_.push_back(type);
65+
msg_types_.push_back(std::string(type));
5866
}
5967
active_msg_type_ = type;
6068
}
@@ -146,7 +154,7 @@ class A2uiStreamParserV09 : public A2uiStreamParserImpl {
146154
return obj.contains(MSG_TYPE_CREATE_SURFACE) || obj.contains(MSG_TYPE_UPDATE_COMPONENTS) || obj.contains(MSG_TYPE_UPDATE_DATA_MODEL);
147155
}
148156

149-
std::string get_active_msg_type_for_components() const override {
157+
std::string_view get_active_msg_type_for_components() const override {
150158
if (!active_msg_type_.empty()) return active_msg_type_;
151159
for (const auto& mt : msg_types_) {
152160
if (mt == MSG_TYPE_UPDATE_COMPONENTS || mt == MSG_TYPE_CREATE_SURFACE) {
@@ -157,7 +165,7 @@ class A2uiStreamParserV09 : public A2uiStreamParserImpl {
157165
return msg_types_.empty() ? "" : msg_types_[0];
158166
}
159167

160-
std::string get_data_model_msg_type() const override {
168+
std::string_view get_data_model_msg_type() const override {
161169
return MSG_TYPE_UPDATE_DATA_MODEL;
162170
}
163171

agent_sdks/cpp/src/schema/catalog.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ A2uiCatalog A2uiCatalog::with_pruned_components(const std::vector<std::string>&
239239
for (auto& item : any_comp["oneOf"]) {
240240
if (item.contains("$ref")) {
241241
std::string ref = item["$ref"].get<std::string>();
242-
std::string prefix = "#/" + CATALOG_COMPONENTS_KEY + "/";
242+
std::string prefix = "#/" + std::string(CATALOG_COMPONENTS_KEY) + "/";
243243
if (ref.rfind(prefix, 0) == 0) {
244244
std::string comp_name = ref.substr(prefix.length());
245245
if (std::find(allowed_components.begin(), allowed_components.end(), comp_name) != allowed_components.end()) {

agent_sdks/cpp/src/schema/manager.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ std::string A2uiSchemaManager::generate_system_prompt(
142142
std::stringstream ss;
143143
ss << role_description << "\n\n";
144144

145-
std::string workflow = DEFAULT_WORKFLOW_RULES;
145+
std::string workflow = std::string(DEFAULT_WORKFLOW_RULES);
146146
if (!workflow_description.empty()) {
147147
workflow += "\n" + workflow_description;
148148
}

0 commit comments

Comments
 (0)