mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Address comments
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
This commit is contained in:
@@ -17,7 +17,12 @@ from jinja2 import Environment, FileSystemLoader
|
||||
import pyparsing as pp
|
||||
|
||||
# Import common utilities
|
||||
from macro_parser_common import CppCleaner, parse_sfields_macro, parse_field_list
|
||||
from macro_parser_common import (
|
||||
CppCleaner,
|
||||
parse_sfields_macro,
|
||||
parse_field_list,
|
||||
generate_cpp_class,
|
||||
)
|
||||
|
||||
|
||||
def create_ledger_entry_parser():
|
||||
@@ -70,7 +75,7 @@ def parse_ledger_entry_args(args_list):
|
||||
value = args_list[1]
|
||||
name = args_list[2]
|
||||
rpc_name = args_list[3]
|
||||
fields_str = args_list[4]
|
||||
fields_str = args_list[-1]
|
||||
|
||||
# Parse fields: ({field1, field2, ...})
|
||||
fields = parse_field_list(fields_str)
|
||||
@@ -115,40 +120,6 @@ def parse_macro_file(file_path):
|
||||
return entries
|
||||
|
||||
|
||||
def generate_cpp_class(entry_info, header_dir, jinja_env, field_types):
|
||||
"""Generate C++ header file for a ledger entry type."""
|
||||
# Enrich field information with type data
|
||||
for field in entry_info["fields"]:
|
||||
field_name = field["name"]
|
||||
if field_name in field_types:
|
||||
field["typed"] = field_types[field_name]["typed"]
|
||||
field["stiSuffix"] = field_types[field_name]["stiSuffix"]
|
||||
field["typeData"] = field_types[field_name]["typeData"]
|
||||
else:
|
||||
# Unknown field - assume typed for safety
|
||||
field["typed"] = True
|
||||
field["stiSuffix"] = None
|
||||
field["typeData"] = None
|
||||
|
||||
template = jinja_env.get_template("LedgerEntry.h.jinja2")
|
||||
|
||||
# Render the template
|
||||
header_content = template.render(
|
||||
name=entry_info["name"],
|
||||
tag=entry_info["tag"],
|
||||
value=entry_info["value"],
|
||||
rpc_name=entry_info["rpc_name"],
|
||||
fields=entry_info["fields"],
|
||||
)
|
||||
|
||||
# Write header file
|
||||
header_path = Path(header_dir) / f"{entry_info['name']}.h"
|
||||
with open(header_path, "w") as f:
|
||||
f.write(header_content)
|
||||
|
||||
print(f"Generated {header_path}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate C++ ledger entry classes from ledger_entries.macro"
|
||||
@@ -157,7 +128,7 @@ def main():
|
||||
parser.add_argument(
|
||||
"--header-dir",
|
||||
help="Output directory for header files",
|
||||
default="include/xrpl/protocol/ledger_objects",
|
||||
default="include/xrpl/protocol_autogen/ledger_objects",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sfields-macro",
|
||||
@@ -207,7 +178,9 @@ def main():
|
||||
header_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for entry in entries:
|
||||
generate_cpp_class(entry, header_dir, jinja_env, field_types)
|
||||
generate_cpp_class(
|
||||
entry, header_dir, jinja_env, field_types, "LedgerEntry.h.jinja2"
|
||||
)
|
||||
|
||||
print(f"\nGenerated {len(entries)} ledger entry classes")
|
||||
|
||||
|
||||
@@ -14,7 +14,12 @@ from jinja2 import Environment, FileSystemLoader
|
||||
import pyparsing as pp
|
||||
|
||||
# Import common utilities
|
||||
from macro_parser_common import CppCleaner, parse_sfields_macro, parse_field_list
|
||||
from macro_parser_common import (
|
||||
CppCleaner,
|
||||
parse_sfields_macro,
|
||||
parse_field_list,
|
||||
generate_cpp_class,
|
||||
)
|
||||
|
||||
|
||||
def create_transaction_parser():
|
||||
@@ -70,7 +75,7 @@ def parse_transaction_args(args_list):
|
||||
delegable = args_list[3]
|
||||
amendments = args_list[4]
|
||||
privileges = args_list[5]
|
||||
fields_str = args_list[6]
|
||||
fields_str = args_list[-1]
|
||||
|
||||
# Parse fields: ({field1, field2, ...})
|
||||
fields = parse_field_list(fields_str)
|
||||
@@ -117,35 +122,6 @@ def parse_macro_file(filepath):
|
||||
return transactions
|
||||
|
||||
|
||||
def generate_cpp_class(tx_info, header_dir, jinja_env, field_types):
|
||||
"""Generate a header-only template class for a transaction using Jinja2 templates."""
|
||||
class_name = tx_info["name"]
|
||||
|
||||
# Enrich field information with type data
|
||||
for field in tx_info["fields"]:
|
||||
field_name = field["name"]
|
||||
if field_name in field_types:
|
||||
field["typed"] = field_types[field_name]["typed"]
|
||||
field["stiSuffix"] = field_types[field_name]["stiSuffix"]
|
||||
field["typeData"] = field_types[field_name]["typeData"]
|
||||
else:
|
||||
# Unknown field - assume typed for safety
|
||||
field["typed"] = True
|
||||
field["stiSuffix"] = None
|
||||
field["typeData"] = None
|
||||
|
||||
# Load template
|
||||
header_template = jinja_env.get_template("Transaction.h.jinja2")
|
||||
|
||||
# Render header
|
||||
header_content = header_template.render(tx_info)
|
||||
header_path = header_dir / f"{class_name}.h"
|
||||
with open(header_path, "w") as f:
|
||||
f.write(header_content)
|
||||
|
||||
return header_path
|
||||
|
||||
|
||||
# TransactionBase is a static file in the repository at:
|
||||
# - include/xrpl/protocol/TransactionBase.h
|
||||
# - src/libxrpl/protocol/TransactionBase.cpp
|
||||
@@ -160,7 +136,7 @@ def main():
|
||||
parser.add_argument(
|
||||
"--header-dir",
|
||||
help="Output directory for header files",
|
||||
default="include/xrpl/protocol/transactions",
|
||||
default="include/xrpl/protocol_autogen/transactions",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sfields-macro",
|
||||
@@ -212,12 +188,14 @@ def main():
|
||||
|
||||
generated_files = []
|
||||
for tx_info in transactions:
|
||||
header_path = generate_cpp_class(tx_info, header_dir, jinja_env, field_types)
|
||||
header_path = generate_cpp_class(
|
||||
tx_info, header_dir, jinja_env, field_types, "Transaction.h.jinja2"
|
||||
)
|
||||
generated_files.append(header_path)
|
||||
print(f" Generated: {tx_info['name']}.h")
|
||||
|
||||
print(
|
||||
f"\n✓ Successfully generated {len(transactions)} transaction classes ({len(generated_files)} header files)"
|
||||
f"\n Successfully generated {len(transactions)} transaction classes ({len(generated_files)} header files)"
|
||||
)
|
||||
print(f" Headers: {header_dir.absolute()}")
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ and ledger_entries.macro files using pcpp and pyparsing.
|
||||
# cspell:words sfields
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
import pyparsing as pp
|
||||
from pcpp import Preprocessor
|
||||
|
||||
@@ -98,9 +99,9 @@ def parse_sfields_macro(sfields_path):
|
||||
"getter_method": "at",
|
||||
"setter_method": "",
|
||||
"setter_use_brackets": True,
|
||||
"setter_type": f"SF_{sti_suffix}::type::value_type const&",
|
||||
"setter_type": f"std::decay_t<typename SF_{sti_suffix}::type::value_type> const&",
|
||||
"return_type": f"SF_{sti_suffix}::type::value_type",
|
||||
"return_type_optional": f"std::optional<SF_{sti_suffix}::type::value_type>",
|
||||
"return_type_optional": f"protocol_autogen::Optional<SF_{sti_suffix}::type::value_type>",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -191,3 +192,41 @@ def parse_field_list(fields_str):
|
||||
return fields
|
||||
except pp.ParseException as e:
|
||||
raise ValueError(f"Failed to parse field list: {e}")
|
||||
|
||||
|
||||
def generate_cpp_class(entry_info, header_dir, jinja_env, field_types, template_name):
|
||||
"""Generate C++ header file from a template.
|
||||
|
||||
Args:
|
||||
entry_info: Dict containing entry information (name, fields, etc.)
|
||||
header_dir: Output directory for generated header files
|
||||
jinja_env: Jinja2 Environment for loading templates
|
||||
field_types: Dict mapping field names to type information
|
||||
template_name: Name of the Jinja2 template file to use
|
||||
"""
|
||||
# Enrich field information with type data
|
||||
for field in entry_info["fields"]:
|
||||
field_name = field["name"]
|
||||
if field_name in field_types:
|
||||
field["typed"] = field_types[field_name]["typed"]
|
||||
field["paramName"] = field_name[2].lower() + field_name[3:]
|
||||
field["stiSuffix"] = field_types[field_name]["stiSuffix"]
|
||||
field["typeData"] = field_types[field_name]["typeData"]
|
||||
else:
|
||||
# Unknown field - assume typed for safety
|
||||
field["typed"] = True
|
||||
field["paramName"] = ""
|
||||
field["stiSuffix"] = None
|
||||
field["typeData"] = None
|
||||
|
||||
template = jinja_env.get_template(template_name)
|
||||
|
||||
# Render the template - pass entry_info directly so templates can access any field
|
||||
header_content = template.render(**entry_info)
|
||||
|
||||
# Write header file
|
||||
header_path = Path(header_dir) / f"{entry_info['name']}.h"
|
||||
with open(header_path, "w") as f:
|
||||
f.write(header_content)
|
||||
|
||||
print(f"Generated {header_path}")
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
|
||||
# cspell:words equalto
|
||||
|
||||
namespace xrpl::ledger_entries {
|
||||
|
||||
// Forward declaration
|
||||
@@ -121,16 +123,21 @@ public:
|
||||
*/
|
||||
class {{ name }}Builder : public LedgerEntryBuilderBase<{{ name }}Builder>
|
||||
{
|
||||
{%- set required_fields = fields | selectattr('requirement', 'equalto', 'soeREQUIRED') | list %}
|
||||
public:
|
||||
{{ name }}Builder()
|
||||
{{ name }}Builder({%- for field in required_fields %}
|
||||
{{ field.typeData.setter_type }} {{ field.paramName }}{% if not loop.last %},{% endif %}
|
||||
{%- endfor %})
|
||||
: LedgerEntryBuilderBase<{{ name }}Builder>({{ tag }})
|
||||
{
|
||||
// Initialize with ledger entry type
|
||||
object_[sfLedgerEntryType] = {{ tag }};
|
||||
{%- for field in required_fields %}
|
||||
set{{ field.name[2:] }}({{ field.paramName }});
|
||||
{%- endfor %}
|
||||
}
|
||||
|
||||
{{ name }}Builder(SLE const& sle)
|
||||
{
|
||||
if (object_[sfLedgerEntryType] != {{ tag }})
|
||||
if (sle[sfLedgerEntryType] != {{ tag }})
|
||||
{
|
||||
throw std::runtime_error("Invalid ledger entry type for {{ name }}");
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
|
||||
# cspell:words equalto
|
||||
|
||||
namespace xrpl::transactions {
|
||||
|
||||
// Forward declaration
|
||||
@@ -124,11 +126,20 @@ public:
|
||||
*/
|
||||
class {{ name }}Builder : public TransactionBuilderBase<{{ name }}Builder>
|
||||
{
|
||||
{%- set required_fields = fields | selectattr('requirement', 'equalto', 'soeREQUIRED') | list %}
|
||||
public:
|
||||
{{ name }}Builder()
|
||||
{{ name }}Builder(SF_ACCOUNT::type::value_type account,
|
||||
SF_UINT32::type::value_type sequence,
|
||||
SF_AMOUNT::type::value_type fee,
|
||||
SF_VL::type::value_type signingPubKey{% if required_fields %},{% endif %}
|
||||
{%- for field in required_fields %}
|
||||
{{ field.typeData.setter_type }} {{ field.paramName }}{% if not loop.last %},{% endif %}
|
||||
{%- endfor %})
|
||||
: TransactionBuilderBase<{{ name }}Builder>(account, sequence, fee, signingPubKey, {{ tag }})
|
||||
{
|
||||
// Initialize with transaction type
|
||||
object_[sfTransactionType] = {{ tag }};
|
||||
{%- for field in required_fields %}
|
||||
set{{ field.name[2:] }}({{ field.paramName }});
|
||||
{%- endfor %}
|
||||
}
|
||||
|
||||
{{ name }}Builder(STTx const& tx)
|
||||
|
||||
Reference in New Issue
Block a user