From 6c506b3111d51a9f8168631d572f41b5d98a9323 Mon Sep 17 00:00:00 2001 From: kevstone Date: Wed, 21 Feb 2024 21:41:12 +0000 Subject: [PATCH] Additions/fixes to improve level 2 compilation count - now at 30 accessors --- src/clang_convert/ast_object/ast_parser.py | 2 +- src/clang_convert/ast_object/ast_utils.py | 59 +---------- src/clang_convert/code_object/array_access.py | 2 +- .../code_object/binary_operation.py | 5 +- src/clang_convert/code_object/code_objects.py | 1 + .../code_object/declaration_specifier.py | 5 +- src/clang_convert/code_object/literal.py | 16 +++ .../code_object/macro_instantation.py | 10 +- src/clang_convert/code_object/operation.py | 8 +- .../code_object/struct_member_access.py | 95 +++++++++++++++++ .../code_object_converter/arg_converter.py | 4 +- .../conversion_pack/code_mappings.py | 5 + .../conversion_pack/conversion_data.py | 30 +++++- .../conversion_pack/conversion_data_helper.py | 19 +++- .../struct_member_access_converter.py | 18 ++-- .../default_conversion_validation.py | 100 +++++++++++++++--- .../grib_accessor_ast_code_converter.py | 3 +- .../grib_accessor/grib_accessor_ccode.py | 6 +- .../grib_accessor_ccode_converter.py | 3 +- .../0TEMPLATE_conversion_pack_updates.py | 16 ++- .../base_conversion_pack_updates.py | 32 ++++-- ...fr_data_element_conversion_pack_updates.py | 29 +++++ .../closest_date_conversion_pack_updates.py | 2 +- ...oustrophedonic_conversion_pack_updates.py} | 21 +++- .../grib_accessor_conversion_validation.py | 61 +++++++---- .../data_shsimple_packing_validation.py | 24 +++++ .../validators/section_pointer_validation.py | 14 +++ .../j2/grib_accessor_header.h.j2 | 2 +- .../supporting/data_member_mappings.py | 9 +- .../grib_buffer_stub_funcsig_mappings.py | 2 +- .../grib_value_stub_funcsig_mappings.py | 3 + .../grib_accessor/supporting/type_mappings.py | 16 +-- src/cpp/CMakeLists.txt | 1 + .../accessor/AccessorData/AccessorData.h | 6 ++ src/cpp/eccodes/accessor/GribCpp/BufrDefs.h | 79 ++++++++++++++ .../eccodes/accessor/GribCpp/GribStatus.cc | 4 +- src/cpp/eccodes/accessor/GribCpp/GribStatus.h | 2 +- .../accessor/GribStub/GribActionStub.h | 4 +- .../accessor/GribStub/GribBufferStub.cc | 2 +- .../accessor/GribStub/GribBufferStub.h | 2 +- .../accessor/GribStub/GribValueStub.cc | 6 ++ .../eccodes/accessor/GribStub/GribValueStub.h | 1 + 42 files changed, 588 insertions(+), 141 deletions(-) create mode 100755 src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/bufr_data_element_conversion_pack_updates.py rename src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/{apply_boustrophedonic_conversion_pack_updates.py => data_apply_boustrophedonic_conversion_pack_updates.py} (51%) create mode 100755 src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/data_shsimple_packing_validation.py create mode 100755 src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/section_pointer_validation.py create mode 100644 src/cpp/eccodes/accessor/GribCpp/BufrDefs.h diff --git a/src/clang_convert/ast_object/ast_parser.py b/src/clang_convert/ast_object/ast_parser.py index c32d92f80..111e3b483 100755 --- a/src/clang_convert/ast_object/ast_parser.py +++ b/src/clang_convert/ast_object/ast_parser.py @@ -838,7 +838,7 @@ class AstParser: debug.line("parse_MEMBER_REF_EXPR", f"[IN] node spelling=[{node.spelling}] type=[{node.type.spelling}] tokens=[{tokens}]") assert len(tokens) >= 3, f"Expected at least 3 tokens for member ref, but got [{len(tokens)}]" - cstruct_member_access = ast_utils.create_code_object_from_tokens(tokens) + cstruct_member_access = ast_utils.create_struct_member_access_from_tokens(tokens) debug.line("parse_MEMBER_REF_EXPR", f"[OUT] cstruct_member_access=[{debug.as_debug_string(cstruct_member_access)}]") diff --git a/src/clang_convert/ast_object/ast_utils.py b/src/clang_convert/ast_object/ast_utils.py index 1bd929779..4769d1607 100755 --- a/src/clang_convert/ast_object/ast_utils.py +++ b/src/clang_convert/ast_object/ast_utils.py @@ -154,59 +154,8 @@ def create_cinit_list(cnode): symbol_tokens = ["[", "]", "->", "."] -# Iterate over list of tokens and create the appropriate code_objects -def create_code_object_from_tokens(tokens, depth=0): - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:IN] tokens={tokens}") +# Iterate over list of tokens and create the appropriate struct_member_access +def create_struct_member_access_from_tokens(tokens, depth=0): + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:IN] tokens={tokens}") - assert len(tokens) != 0 - name = "" - - # Build the name from the non-symbol token(s) - for tok in list(tokens): - if tok not in symbol_tokens: - name += tokens.pop(0) - else: - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] name = [{debug.as_debug_string(name)}] tokens={tokens}") - break - - assert name and name not in symbol_tokens, f"Name token can't be in {symbol_tokens}!" - name_obj = literal.Literal(name) - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]") - - if len(tokens) == 0: - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:OUT] No more tokens: name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]") - return name_obj - - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.1] tokens={tokens}") - symbol = tokens.pop(0) - - if symbol == "[": - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] Found a [ - creating an array access object, tokens={tokens}") - index_obj = create_code_object_from_tokens(tokens, depth+1) - array_access_obj = array_access.ArrayAccess(name_obj, index_obj) - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] array_access_obj=[{debug.as_debug_string(array_access_obj)}] [{type(array_access_obj)}] tokens={tokens}") - name_obj = array_access_obj - if len(tokens) == 0: - return name_obj - symbol = tokens.pop(0) - - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.2] tokens={tokens}") - - if symbol == "]": - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:OUT] Found ], name_obj=[{debug.as_debug_string(name_obj)}] tokens={tokens}") - return name_obj - - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.3] tokens={tokens}") - - if symbol in ["->", "."]: - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] Creating StructMemberAccess from tokens={tokens}") - member_name_obj = create_code_object_from_tokens(tokens, depth+1) - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_name_obj=[{debug.as_debug_string(member_name_obj)}]") - member_obj = struct_member_access.StructMemberAccess(symbol, member_name_obj) - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_obj=[{debug.as_debug_string(member_obj)}]") - struct_member_access_obj = struct_member_access.StructMemberAccess("", name_obj, member_obj) - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:OUT] struct_member_access_obj=[{debug.as_debug_string(struct_member_access_obj)}] [{type(struct_member_access_obj)}]") - return struct_member_access_obj - - debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.4] tokens={tokens}") - assert False, "Didn't expect to get here! tokens={tokens}" \ No newline at end of file + return struct_member_access.create_struct_member_access_from_tokens(tokens) diff --git a/src/clang_convert/code_object/array_access.py b/src/clang_convert/code_object/array_access.py index 8b0254eec..c16ceee0c 100755 --- a/src/clang_convert/code_object/array_access.py +++ b/src/clang_convert/code_object/array_access.py @@ -22,4 +22,4 @@ class ArrayAccess(code_interface.CodeInterface): return self._index def as_lines(self): - return [f"{strip_semicolon(self._name.as_string())}[{self._index.as_string()}]"] + return [f"{strip_semicolon(self._name.as_string())}[{strip_semicolon(self._index.as_string())}]"] diff --git a/src/clang_convert/code_object/binary_operation.py b/src/clang_convert/code_object/binary_operation.py index 592bb884c..c16653b13 100755 --- a/src/clang_convert/code_object/binary_operation.py +++ b/src/clang_convert/code_object/binary_operation.py @@ -51,7 +51,8 @@ class BinaryOperation(code_interface.CodeInterface): lines.extend(right_lines[1:]) # Determine whether to add a ; - if self._binary_op.is_assignment() and not lines[-1].endswith(";"): - lines[-1] += ";" + if self._binary_op.is_assignment() or self._binary_op.is_arithmetic(): + if not lines[-1].endswith(";"): + lines[-1] += ";" return lines \ No newline at end of file diff --git a/src/clang_convert/code_object/code_objects.py b/src/clang_convert/code_object/code_objects.py index 3f188a8ec..d85f9eaa8 100755 --- a/src/clang_convert/code_object/code_objects.py +++ b/src/clang_convert/code_object/code_objects.py @@ -1,5 +1,6 @@ import code_object.code_interface as code_interface import code_object.code_objects as code_objects +from utils import debug # Represents a group of code objects (CodeInterface classes) that make up a coherent collection of code (e.g. a function body) # Provides convenient ways of accessing the underlying code diff --git a/src/clang_convert/code_object/declaration_specifier.py b/src/clang_convert/code_object/declaration_specifier.py index 030552a57..ad82238d7 100755 --- a/src/clang_convert/code_object/declaration_specifier.py +++ b/src/clang_convert/code_object/declaration_specifier.py @@ -113,7 +113,10 @@ class DeclSpec(code_interface.CodeInterface): def is_array_type(self): return self._pointer.startswith("[") - + + def is_raw_pointer(self): + return self._pointer.startswith("*") + def array_size(self): if self.is_array_type() and len(self._pointer) > 2: return self._pointer[1:-1] diff --git a/src/clang_convert/code_object/literal.py b/src/clang_convert/code_object/literal.py index 5a4d3b80a..a90807c7d 100755 --- a/src/clang_convert/code_object/literal.py +++ b/src/clang_convert/code_object/literal.py @@ -1,5 +1,6 @@ import utils.debug as debug import code_object.code_interface as code_interface +from code_object.code_interface import NONE_VALUE # Represents any literal: integer, float, char, string (quoted) class Literal(code_interface.CodeInterface): @@ -10,5 +11,20 @@ class Literal(code_interface.CodeInterface): def value(self): return self._value + # ---------- Support for use as a dict key: Begin ---------- + def __hash__(self): + return hash((self.value)) + + def __eq__(self, other): + if self is NONE_VALUE or other is NONE_VALUE: + return self is other + + # Ensure the other object is an instance of StructMemberAccess for comparison. + if not isinstance(other, Literal): + return False + + return self.value == other.value + # ---------- Support for use as a dict key: End ---------- + def as_lines(self): return [f"{self._value}"] \ No newline at end of file diff --git a/src/clang_convert/code_object/macro_instantation.py b/src/clang_convert/code_object/macro_instantation.py index 309ac42a0..9ee58bb7b 100755 --- a/src/clang_convert/code_object/macro_instantation.py +++ b/src/clang_convert/code_object/macro_instantation.py @@ -1,5 +1,6 @@ import code_object.code_interface as code_interface import code_object.code_objects as code_objects +from utils import debug # Represents a macro instantiation, for example # BAR(42) @@ -24,7 +25,12 @@ class MacroInstantation(code_interface.CodeInterface): return self._expression def as_lines(self): - text = f"{self._name}{self._expression.as_string()};" + # Ensure it is all on one line! - text = text.replace("\n", "") + expression_string = self._expression.as_string().replace("\n", "") + + if expression_string.endswith(";)"): + expression_string = expression_string[:-2] + ")" + + text = f"{self._name}{expression_string};" return [text] diff --git a/src/clang_convert/code_object/operation.py b/src/clang_convert/code_object/operation.py index a1c520ead..96ad9c288 100755 --- a/src/clang_convert/code_object/operation.py +++ b/src/clang_convert/code_object/operation.py @@ -19,14 +19,16 @@ class Operation(code_interface.CodeInterface): return [f"{self._value}"] def is_assignment(self): - return self._value in ["=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="] + return self._value in ["="] + #return self._value in ["=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="] def is_inc_dec(self): return self._value in ["++", "--"] def is_arithmetic(self): - return self._value in ["+", "-", "*", "/", "%", "~", "&", "|", "^", "<<", ">>"] - + return self._value in ["+", "-", "*", "/", "%", "~", "&", "|", "^", "<<", ">>", #] + "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="] + def is_logical(self): return self._value in ["!", "&&", "||"] diff --git a/src/clang_convert/code_object/struct_member_access.py b/src/clang_convert/code_object/struct_member_access.py index 4fc38ed23..1f6efd2ba 100755 --- a/src/clang_convert/code_object/struct_member_access.py +++ b/src/clang_convert/code_object/struct_member_access.py @@ -1,7 +1,10 @@ import code_object.code_interface as code_interface +import code_object.literal as literal +import code_object.array_access as array_access import utils.debug as debug from code_object.code_interface import NONE_VALUE +import re # Represent the accessing of a struct member as defined in code, in order to manipulate/transform it # @@ -56,6 +59,22 @@ class StructMemberAccess(code_interface.CodeInterface): assert isinstance(value, StructMemberAccess), f"Member must be a StructMemberAccess class" self._member = value + # ---------- Support for use as a dict key: Begin ---------- + def __hash__(self): + return hash((self.access, self._variable, self._member)) + + def __eq__(self, other): + if self is NONE_VALUE or other is NONE_VALUE: + return self is other + + # Ensure the other object is an instance of StructMemberAccess for comparison. + if not isinstance(other, StructMemberAccess): + return False + + return self.access == other.access and self.variable == other.variable and self.member == other.member + # ---------- Support for use as a dict key: End ---------- + + def as_lines(self): access_str = self._access if self._access is not None else "" access_str += self._variable.as_string() if self._variable is not None else "" @@ -66,3 +85,79 @@ class StructMemberAccess(code_interface.CodeInterface): access_str += ";" return [access_str] + +symbol_tokens = ["[", "]", "->", "."] +# Create from tokens e.g. ["a","->","b","->","c"] +def create_struct_member_access_from_tokens(tokens, depth=0): + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:IN] tokens={tokens}") + + assert len(tokens) != 0 + name = "" + + # Build the name from the non-symbol token(s) + for tok in list(tokens): + if tok not in symbol_tokens: + name += tokens.pop(0) + else: + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] name = [{debug.as_debug_string(name)}] tokens={tokens}") + break + + assert name and name not in symbol_tokens, f"Name token can't be in {symbol_tokens}!" + name_obj = literal.Literal(name) + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]") + + if len(tokens) == 0: + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:OUT] No more tokens: name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]") + return name_obj + + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.1] tokens={tokens}") + symbol = tokens.pop(0) + + if symbol == "[": + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] Found a [ - creating an array access object, tokens={tokens}") + index_obj = create_struct_member_access_from_tokens(tokens, depth+1) + array_access_obj = array_access.ArrayAccess(name_obj, index_obj) + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] array_access_obj=[{debug.as_debug_string(array_access_obj)}] [{type(array_access_obj)}] tokens={tokens}") + name_obj = array_access_obj + if len(tokens) == 0: + return name_obj + symbol = tokens.pop(0) + + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.2] tokens={tokens}") + + if symbol == "]": + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:OUT] Found ], name_obj=[{debug.as_debug_string(name_obj)}] tokens={tokens}") + return name_obj + + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.3] tokens={tokens}") + + if symbol in ["->", "."]: + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] Creating StructMemberAccess from tokens={tokens}") + member_name_obj = create_struct_member_access_from_tokens(tokens, depth+1) + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_name_obj=[{debug.as_debug_string(member_name_obj)}]") + member_obj = StructMemberAccess(symbol, member_name_obj) + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_obj=[{debug.as_debug_string(member_obj)}]") + struct_member_access_obj = StructMemberAccess("", name_obj, member_obj) + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:OUT] struct_member_access_obj=[{debug.as_debug_string(struct_member_access_obj)}] [{type(struct_member_access_obj)}]") + return struct_member_access_obj + + debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.4] tokens={tokens}") + assert False, f"Didn't expect to get here! tokens={tokens}" + +# Helper to create from a string e.g. "a->b->c->" +def struct_member_access_from_string(tokenstring, depth=0): + + # Create a regular expression pattern that captures any of the tokens + # and also matches sequences of characters that are not the tokens + # The pattern has two parts: + # 1. A non-capturing group (?:...) with alternatives for each token, escaped as needed + # 2. A segment to match any sequence of characters not matching the first part, using [^...]+ + pattern = '(' + '|'.join(re.escape(token) for token in symbol_tokens) + ')|([^' + ''.join(re.escape(token) for token in symbol_tokens) + ']+)' + + # Use re.findall() with the pattern to find all matches, including tokens + matches = re.findall(pattern, tokenstring) + + # Flatten the resulting list of tuples and filter out empty strings + tokens = [item for sublist in matches for item in sublist if item] + + return create_struct_member_access_from_tokens(tokens) diff --git a/src/clang_convert/code_object_converter/arg_converter.py b/src/clang_convert/code_object_converter/arg_converter.py index 979394b57..2a822a32a 100755 --- a/src/clang_convert/code_object_converter/arg_converter.py +++ b/src/clang_convert/code_object_converter/arg_converter.py @@ -38,7 +38,7 @@ class ArgConverter(code_interface_converter.CodeInterfaceConverter): if cpp_arg: return cpp_arg - debug.line("convert_funcsig_arg", f"--[2]-- carg=[{debug.as_debug_string(cpp_arg)}]") + debug.line("convert_funcsig_arg", f"--[2]-- cpp_arg=[{debug.as_debug_string(cpp_arg)}]") # 2. Check if the C type should not be converted (e.g. grib_handle*) test_decl_spec = declaration_specifier.DeclSpec.from_instance(carg.decl_spec) @@ -86,6 +86,8 @@ class ArgConverter(code_interface_converter.CodeInterfaceConverter): cpp_arg = arg.Arg(new_decl_spec, cpp_name, cpp_is_func_arg) + debug.line("create_funcsig_cpparg", f"Created cpp_arg=[{debug.as_debug_string(cpp_arg)}] from carg=[{debug.as_debug_string(carg)}]") + self._conversion_pack.conversion_data.add_funcsig_arg_mapping(carg, cpp_arg) debug.line("create_funcsig_cpparg", f"Arg conversion arg mapping: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpp_arg)}]") diff --git a/src/clang_convert/code_object_converter/conversion_pack/code_mappings.py b/src/clang_convert/code_object_converter/conversion_pack/code_mappings.py index ac0f4c84b..28bbe29d0 100755 --- a/src/clang_convert/code_object_converter/conversion_pack/code_mappings.py +++ b/src/clang_convert/code_object_converter/conversion_pack/code_mappings.py @@ -10,6 +10,7 @@ class CodeMappings: self._funcsig_type_mappings = {} self._funcsig_buffer_mappings = [] # Don't expect more than one entry, but just in case! self._data_member_mappings = {} + self._struct_member_access_mappings = {} self._funcsig_mappings = [] self._funcsig_pointer_mappings = [] self._member_funcsig_mappings = [] @@ -43,6 +44,10 @@ class CodeMappings: def data_member_mappings(self): return self._data_member_mappings + @property + def struct_member_access_mappings(self): + return self._struct_member_access_mappings + @property def all_funcsig_mappings(self): return self._funcsig_mappings + self._member_funcsig_mappings + self._virtual_member_funcsig_mappings diff --git a/src/clang_convert/code_object_converter/conversion_pack/conversion_data.py b/src/clang_convert/code_object_converter/conversion_pack/conversion_data.py index b7b54ba98..b19f1f6e3 100755 --- a/src/clang_convert/code_object_converter/conversion_pack/conversion_data.py +++ b/src/clang_convert/code_object_converter/conversion_pack/conversion_data.py @@ -8,6 +8,7 @@ from code_object.arg import Arg from code_object.function_call import FunctionCall from code_object.funcsig import FuncSig from code_object.data_member import DataMember +from code_object.struct_member_access import StructMemberAccess from code_object.declaration_specifier import DeclSpec from code_object_converter.conversion_pack.conversion_data_helper import * from code_object.code_interface import NONE_VALUE @@ -58,6 +59,10 @@ class ConversionData: else: return [self._global_mappings] + @property + def current_cfuncname(self): + return self._current_cfuncname + # ============================== Funcsig mappings: start ============================== # ------------------------------ SET ------------------------------ @@ -201,6 +206,11 @@ class ConversionData: def add_funcsig_arg_mapping(self, carg, cpparg): assert isinstance(carg, Arg), f"Expected Arg, got [{carg}]" assert isinstance(cpparg, Arg) or cpparg==NONE_VALUE, f"Expected Arg, got [{cpparg}]" + + if not carg.name or (cpparg and cpparg != NONE_VALUE and not cpparg.name): + debug.line("add_funcsig_arg_mapping", f"*** WARNING *** Not adding arg mapping due to missing name (must be an anonymous/unused funcsig arg) : carg=[{debug.as_debug_string(carg)}] cpparg=[{debug.as_debug_string(cpparg)}]") + return + if carg in self.active_map.funcsig_arg_mappings: assert self.active_map.funcsig_arg_mappings[carg] == cpparg, f"Updating an existing funcsig arg: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpparg)}] Previous function arg=[{debug.as_debug_string(self.active_map.funcsig_arg_mappings[carg])}]" else: @@ -265,6 +275,7 @@ class ConversionData: # See conversion_data_helper.find_best_matching_cdecl_spec() for more info # def closest_funcbody_cppdecl_spec_for_cdecl_spec(self, cdecl_spec): + matches = [] for mapping in self.all_mappings(): for key, value in mapping.funcbody_type_mappings.items(): @@ -348,6 +359,16 @@ class ConversionData: self.active_map.data_member_mappings[cmember] = cppmember debug.line("add_data_member_mapping", f"Adding data member: [{debug.as_debug_string(cmember)}] -> [{debug.as_debug_string(cppmember)}]") + def add_struct_member_access_mapping(self, cstruct_member_access, cppstruct_member_access): + assert isinstance(cstruct_member_access, StructMemberAccess), f"Expected StructMemberAccess, got [{cstruct_member_access}]" + assert isinstance(cppstruct_member_access, StructMemberAccess) or cppstruct_member_access==NONE_VALUE, f"Expected StructMemberAccess, got [{cppstruct_member_access}]" + + if cstruct_member_access in self.active_map.struct_member_access_mappings: + assert self.active_map.struct_member_access_mappings[cstruct_member_access] == cppstruct_member_access, f"Updating an existing data member: [{debug.as_debug_string(cstruct_member_access)}] -> [{debug.as_debug_string(cppstruct_member_access)}] Previous value=[{debug.as_debug_string(self.active_map.data_member_mappings[cstruct_member_access])}]" + else: + self.active_map.struct_member_access_mappings[cstruct_member_access] = cppstruct_member_access + debug.line("add_struct_member_access_mapping", f"Adding StructMemberAccess: [{debug.as_debug_string(cstruct_member_access)}] -> [{debug.as_debug_string(cppstruct_member_access)}]") + def add_literal_mapping(self, cstring, cppstring): assert isinstance(cstring, str), f"Expected str, got [{cstring}]" assert isinstance(cppstring, str), f"Expected str, got [{cppstring}]" @@ -491,7 +512,14 @@ class ConversionData: return value return None - #def funcsig_buffer_mapping_for + def get_cppstruct_member_access(self, cstruct_member_access): + + for mapping in self.all_mappings(): + for key, value in mapping.struct_member_access_mappings.items(): + if key == cstruct_member_access: + return value + + return None # Searches both C and C++ member and virtual member maps # NOTE: cppfuncsig will be none for "discovered" virtual functions until they have been converted! diff --git a/src/clang_convert/code_object_converter/conversion_pack/conversion_data_helper.py b/src/clang_convert/code_object_converter/conversion_pack/conversion_data_helper.py index 1308e4330..9f9d86f69 100755 --- a/src/clang_convert/code_object_converter/conversion_pack/conversion_data_helper.py +++ b/src/clang_convert/code_object_converter/conversion_pack/conversion_data_helper.py @@ -76,13 +76,26 @@ def create_best_matching_cdecl_spec(cdecl_spec, matches): # Rank the results ranked_scored_matches = sorted(scored_matches.items(), key=lambda x: x[1], reverse=True) result, score = ranked_scored_matches[0] - debug.line("create_best_matching_cdecl_spec", f" Result: key=[{debug.as_debug_string(result[key])}] value=[{debug.as_debug_string(result[value])}] match=[{score}]") + + result_decl_spec = result[value] + debug.line("create_best_matching_cdecl_spec", f" Result: key=[{debug.as_debug_string(result[key])}] value=[{debug.as_debug_string(result_decl_spec)}] match=[{score}]") # Create the new DeclSpec - if result[value] == NONE_VALUE: + if result_decl_spec == NONE_VALUE: new_decl_spec = NONE_VALUE else: - new_decl_spec = declaration_specifier.DeclSpec.from_instance(result[value]) + # Check we're not assigning a container to a non-container type + if cdecl_spec.pointer == "" and result_decl_spec.type.startswith("std::"): + if result_decl_spec.type == "std::string": + new_decl_spec = declaration_specifier.DeclSpec.from_decl_specifier_seq("char") + else: + # Assume it is std::CONTAINER + start = result_decl_spec.type.index("<") + 1 + end = result_decl_spec.type.index(">") + new_decl_spec = declaration_specifier.DeclSpec.from_decl_specifier_seq(result_decl_spec.type[start:end]) + else: + new_decl_spec = declaration_specifier.DeclSpec.from_instance(result_decl_spec) + if not (score & DeclSpecMatchType.POINTER.value): new_decl_spec.pointer = cdecl_spec.pointer diff --git a/src/clang_convert/code_object_converter/struct_member_access_converter.py b/src/clang_convert/code_object_converter/struct_member_access_converter.py index 2edd43f57..72d72b922 100755 --- a/src/clang_convert/code_object_converter/struct_member_access_converter.py +++ b/src/clang_convert/code_object_converter/struct_member_access_converter.py @@ -15,14 +15,20 @@ class StructMemberAccessConverter(code_interface_converter.CodeInterfaceConverte def create_cpp_code_object(self, conversion_pack): self._conversion_pack = conversion_pack cstruct_member_access = self._ccode_object - cppstruct_member_access = None + debug.line("create_cpp_code_object",f"StructMemberAccessConverter [IN] cstruct_member_access=[{debug.as_debug_string(cstruct_member_access)}]") - # Check if this is a pointer to a class member - variable_name = arg_utils.extract_name(cstruct_member_access.variable) - if conversion_pack.conversion_data.is_self_class_pointer_name(variable_name): - debug.line("create_cpp_code_object",f"StructMemberAccessConverter [1] cstruct_member_access.variable=[{debug.as_debug_string(cstruct_member_access.variable)}] is a self class pointer variable") - cppstruct_member_access = self.try_to_convert_data_member_access(cstruct_member_access.member) + # Do we have a mapping? + cppstruct_member_access = conversion_pack.conversion_data.get_cppstruct_member_access(cstruct_member_access) + debug.line("create_cpp_code_object",f"StructMemberAccessConverter Mapping check: cppstruct_member_access=[{debug.as_debug_string(cppstruct_member_access)}]") + + if not cppstruct_member_access: + # Check if this is a pointer to a class member + variable_name = arg_utils.extract_name(cstruct_member_access.variable) + debug.line("create_cpp_code_object",f"StructMemberAccessConverter [1.1] variable_name=[{debug.as_debug_string(variable_name)}]") + if conversion_pack.conversion_data.is_self_class_pointer_name(variable_name): + debug.line("create_cpp_code_object",f"StructMemberAccessConverter [1.2] cstruct_member_access.variable=[{debug.as_debug_string(cstruct_member_access.variable)}] is a self class pointer variable") + cppstruct_member_access = self.try_to_convert_data_member_access(cstruct_member_access.member) if not cppstruct_member_access: # Check if the primary member is valid... diff --git a/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py b/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py index 80a4f9a1e..ef49e03d1 100755 --- a/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py +++ b/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py @@ -12,9 +12,11 @@ import code_object_converter.conversion_pack.arg_utils as arg_utils import code_object.variable_declaration as variable_declaration import code_object.paren_expression as paren_expression import code_object.array_access as array_access +import code_object.if_statement as if_statement from code_object_converter.conversion_utils import as_commented_out_code from utils.string_funcs import is_number import code_object.cast_expression as cast_expression +from utils.string_funcs import strip_semicolon # Pass this to the conversion_data object to be accessed by the conversion routines class DefaultConversionValidation(conversion_validation.ConversionValidation): @@ -112,9 +114,9 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): cpp_empty_call = literal.Literal(f"{cpparg.name}.empty()") debug.line("validate_unary_operation", f"Updating empty evaluation: [{debug.as_debug_string(cppunary_operation)}]->[{debug.as_debug_string(cpp_empty_call)}]") return cpp_empty_call - else: + elif cppunary_operation.unary_op.value[0] in ["*", "&", "["]: # C++ variable is a container, so we'll strip the * - debug.line("validate_unary_operation", f"Stripping [*] from cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]") + debug.line("validate_unary_operation", f"Stripping [{cppunary_operation.unary_op.value[0]}] from cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]") return cppunary_operation.operand elif cpparg.decl_spec.pointer == "&" and cppunary_operation.unary_op.is_member_access(): debug.line("validate_unary_operation", f"Stripping [*] from ref type: current cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]") @@ -161,7 +163,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): elif cppright.as_string() == "0": cppleft.member.name = literal.Literal("clear()") else: - cppleft.member.name = literal.Literal(f"resize({cppright.as_string()})") + cppleft.member.name = literal.Literal(f"resize({strip_semicolon(cppright.as_string())})") # Double-check it's not const! debug.line("validate_binary_operation", f"Performing const check cppleft.name=[{debug.as_debug_string(cppleft.name)}] cpparg=[{debug.as_debug_string(cpparg)}]") @@ -172,12 +174,16 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): # See if we're assigning a single value to a container type if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type): - cppright_value = cppright.as_string() + right_cpparg = arg_utils.to_cpparg(cppright, self._conversion_data) + if right_cpparg and self._conversion_data.is_container_type(right_cpparg.decl_spec.type): + debug.line("validate_binary_operation", f"Assigning container to container - nothing to do: left arg=[{debug.as_debug_string(cpparg)}] right arg=[{debug.as_debug_string(right_cpparg)}]") + else: + cppright_value = cppright.as_string() - if is_number(cppright_value) or not self.is_cppfunction_returning_container(cppright): - cppleft = array_access.ArrayAccess(cppleft.name, literal.Literal("0")) - debug.line("validate_binary_operation", f"Assigning number to container, so updating it to access first element: cppleft=[{debug.as_debug_string(cppleft)}] cppright_value=[{cppright_value}]") - return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + if is_number(cppright_value) or not self.is_cppfunction_returning_container(cppright): + cppleft = array_access.ArrayAccess(cppleft.name, literal.Literal("0")) + debug.line("validate_binary_operation", f"Assigning number to container, so updating it to access first element: cppleft=[{debug.as_debug_string(cppleft)}] cppright_value=[{cppright_value}]") + return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) # Check if we're assigning to a data member and need to ensure the function is non-const data_member_name = arg_utils.extract_name(cppleft.name) @@ -186,11 +192,32 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): if self._conversion_data.is_cppdata_member(data_member_name): self._conversion_data.set_current_cfuncname_non_const() + else: + # Other checks when assigning a container to a variable... + left_cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data) + right_cpparg = arg_utils.to_cpparg(cppright, self._conversion_data) + + if left_cpparg and right_cpparg: + debug.line("validate_binary_operation", f"Container assignment check: left_cpparg=[{debug.as_debug_string(left_cpparg)}] right_cpparg=[{debug.as_debug_string(right_cpparg)}] ") + if self._conversion_data.is_container_type(right_cpparg.decl_spec.type) and \ + not self._conversion_data.is_container_type(left_cpparg.decl_spec.type): + if left_cpparg.decl_spec.is_raw_pointer(): + # We are assigning a container value to a pointer arg, so need to call .data() + cppright = literal.Literal(f"{right_cpparg.name}.data()") + return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + if not left_cpparg.decl_spec.pointer: + # We are assigning a container value to a basic variable, so use index 0 + cppright = array_access.ArrayAccess(literal.Literal(right_cpparg.name), literal.Literal("0")) + return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + elif cppbinary_op.is_comparison(): cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data) if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type): - cppleft = literal.Literal(f"{cpparg.name}.size()") - return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + if cppright.as_string() in ["NULL", "0"]: + return literal.Literal(f"{cpparg.name}.empty()") + else: + cppleft = literal.Literal(f"{cpparg.name}.size()") + return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) elif cppbinary_op.value == "+": cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data) @@ -199,7 +226,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): cpparray_access = array_access.ArrayAccess(literal.Literal(cpparg.name), cppright) return cpparray_access - elif cppbinary_op.is_arithmetic: + elif cppbinary_op.is_arithmetic(): cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data) if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type): # We'll assume the arithmetic is against index 0 @@ -211,6 +238,11 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): return updated_cppbinary_operation + elif cppbinary_op.is_logical(): + cppleft = self.try_to_make_boolean(cppleft) + cppright = self.try_to_make_boolean(cppright) + return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + return cppbinary_operation def validate_variable_declaration(self, cvariable_declaration, cppvariable_declaration): @@ -225,14 +257,38 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): cppcontainer_constructor_call = literal.Literal(f"{cppvariable.as_string()}({cvariable.decl_spec.array_size()},{{}});") debug.line("validate_variable_declaration", f"Creating cppvariable=[{debug.as_debug_string(cppvariable)}] with initial size=[{cvariable.decl_spec.array_size()}] cppcontainer_constructor_call=[{debug.as_debug_string(cppcontainer_constructor_call)}]") return cppcontainer_constructor_call - if cppvalue.as_string() == "NULL": + if cppvalue.as_string() in ["NULL", "0"]: # Init as {} debug.line("validate_variable_declaration", f"Changing NULL initialiser for container cppvariable=[{debug.as_debug_string(cppvariable)}] to [= {{}}") cppvalue = literal.Literal("{}") return variable_declaration.VariableDeclaration(cppvariable, cppvalue) + # Checks when assigning a container to a variable... + variable_cpparg = arg_utils.to_cpparg(cppvariable, self._conversion_data) + value_cpparg = arg_utils.to_cpparg(cppvariable_declaration.value, self._conversion_data) + + if variable_cpparg and value_cpparg: + debug.line("validate_variable_declaration", f"Container assignment check: variable_cpparg=[{debug.as_debug_string(variable_cpparg)}] value_cpparg=[{debug.as_debug_string(value_cpparg)}] ") + if self._conversion_data.is_container_type(value_cpparg.decl_spec.type) and \ + not self._conversion_data.is_container_type(variable_cpparg.decl_spec.type): + if variable_cpparg.decl_spec.is_raw_pointer(): + # We are assigning a container value to a pointer arg, so need to call .data() + updated_value = literal.Literal(f"{value_cpparg.name}.data()") + return variable_declaration.VariableDeclaration(cppvariable, updated_value) + if not variable_cpparg.decl_spec.pointer: + # We are assigning a container value to a basic variable, so use index 0 + updated_value = array_access.ArrayAccess(literal.Literal(value_cpparg.name), literal.Literal("0")) + return variable_declaration.VariableDeclaration(cppvariable, updated_value) + return cppvariable_declaration + def validate_if_statement(self, cif_statement, cppif_statement): + + cppexpression = self.try_to_make_boolean(cppif_statement.expression) + + return if_statement.IfStatement(cppexpression, cppif_statement.action) + + # Helper to determine how a container should receive the value returned by the function # Returns True if the function returns e.g. std::vector instead of int # Override as required... @@ -244,4 +300,22 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): if cppfuncsig and self._conversion_data.is_container_type(cppfuncsig.return_type.type): return True - return False \ No newline at end of file + return False + + # If there is a boolean output available, return it, else just return the original object + # + # NOTE: Add more types as required (perhaps put in a separate class/file?) + def try_to_make_boolean(self, cppcode_object): + + if isinstance(cppcode_object, unary_operation.UnaryOperation): + cpparg = arg_utils.to_cpparg(cppcode_object.operand, self._conversion_data) + if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type): + updated_operand = literal.Literal(f"{cpparg.name}.empty()") + return unary_operation.UnaryOperation(cppcode_object.unary_op, updated_operand, cppcode_object.op_position) + + if isinstance(cppcode_object, struct_member_access.StructMemberAccess): + cpparg = arg_utils.to_cpparg(cppcode_object.name, self._conversion_data) + if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type): + return literal.Literal(f"{cpparg.name}.empty()") + + return cppcode_object \ No newline at end of file diff --git a/src/clang_convert/grib_accessor/grib_accessor_ast_code_converter.py b/src/clang_convert/grib_accessor/grib_accessor_ast_code_converter.py index b6db7865e..14a12ff5d 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_ast_code_converter.py +++ b/src/clang_convert/grib_accessor/grib_accessor_ast_code_converter.py @@ -17,7 +17,8 @@ class GribAccessorAstCodeConverter(default_ast_code_converter.DefaultAstCodeConv def create_ccode(self): cfilename = self._ast_code.cfilename - self._accessor_class_name = cfilename.rstrip(".cc") + assert cfilename.endswith(".cc"), f"Expected filename=[{cfilename}] to have .cc extension" + self._accessor_class_name = cfilename[:-3] self._accessor_name = self._accessor_class_name.replace("grib_accessor_class", "grib_accessor") self._ccode = grib_accessor_ccode.GribAccessorCCode(cfilename, self._accessor_name, self._accessor_class_name) diff --git a/src/clang_convert/grib_accessor/grib_accessor_ccode.py b/src/clang_convert/grib_accessor/grib_accessor_ccode.py index 4a31dbad4..5c23b3f3a 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_ccode.py +++ b/src/clang_convert/grib_accessor/grib_accessor_ccode.py @@ -34,9 +34,9 @@ class GribAccessorCCode(default_ccode.DefaultCCode): def is_member_function(self, cfuncsig): if not self.is_virtual_member_function(cfuncsig): - # If any arg starts with a "ptr type name", then it's a member function (as we've already extracted virtual functions) - for arg_entry in cfuncsig.args: - if re.search(r"grib_accessor(\w*)?\s*\*", arg_entry.decl_spec.as_string()): + # If first arg starts with a "ptr type name", then it's a member function (as we've already extracted virtual functions) + if len(cfuncsig.args) > 0: + if re.search(r"grib_accessor(\w*)?\s*\*", cfuncsig.args[0].decl_spec.as_string()): return True return False diff --git a/src/clang_convert/grib_accessor/grib_accessor_ccode_converter.py b/src/clang_convert/grib_accessor/grib_accessor_ccode_converter.py index 73637a74e..c777c8119 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_ccode_converter.py +++ b/src/clang_convert/grib_accessor/grib_accessor_ccode_converter.py @@ -121,7 +121,7 @@ class GribAccessorCCodeConverter(default_ccode_converter.DefaultCCodeConverter): for mapping in grib_accessor_virtual_member_funcsig_mapping: conv_data.add_global_virtual_member_funcsig_mapping(mapping) - self._conversion_pack_updates.add_funcsig_mappings_to_conversion_data(conv_data) + self._conversion_pack_updates.add_accessor_wide_conversion_data(conv_data) all_funcsig_mappings.add_all_funcsig_mappings_to_conversion_data(conv_data) @@ -153,6 +153,7 @@ class GribAccessorCCodeConverter(default_ccode_converter.DefaultCCodeConverter): conv_pack.conversion_data.info.header_includes.append(inc) # Source includes + debug.line("SOURCE INCLUDE", f"class_name=[{conv_pack.conversion_data.info.class_name}] Header Entry=[\"{conv_pack.conversion_data.info.class_name}.h\"]") conv_pack.conversion_data.info.source_includes.append(f"\"{conv_pack.conversion_data.info.class_name}.h\"") for inc in includes.grib_accessor_source_includes: diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/0TEMPLATE_conversion_pack_updates.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/0TEMPLATE_conversion_pack_updates.py index 633789295..a78320e66 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/0TEMPLATE_conversion_pack_updates.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/0TEMPLATE_conversion_pack_updates.py @@ -6,6 +6,8 @@ from code_object_converter.conversion_pack.funcsig_mapping import FuncSigMapping from code_object_converter.conversion_pack.arg_indexes import ArgIndexes from code_object.funcsig import FuncSig from code_object.code_interface import NONE_VALUE +from code_object.data_member import DataMember +from code_object.struct_member_access import create_struct_member_access_from_tokenstring class TemplateConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates): def __init__(self) -> None: @@ -15,7 +17,11 @@ class TemplateConversionPackUpdates(base_conversion_pack_updates.BaseConversionP "pack_long": self.apply_updates_for_pack_long }) - self._include_files.extend([ + self._header_includes.extend([ + "BufrDefs.h", + ]) + + self._source_includes.extend([ "", ]) @@ -30,5 +36,13 @@ class TemplateConversionPackUpdates(base_conversion_pack_updates.BaseConversionP Arg("unsigned char*","p") : Arg("AccessorDataPointer","p"), }) + self._data_member_mappings.update({ + DataMember("foo*", "bar"): DataMember("Foo", "bar_"), + }) + + self._all_function_struct_member_access_mappings.update({ + create_struct_member_access_from_tokenstring("foo->bar"): create_struct_member_access_from_tokenstring("foo_.bar_"), + }) + def apply_updates_for_pack_long(self, conversion_pack): conversion_pack.conversion_data.add_funcbody_arg_mapping(Arg("unsigned char*","mdata"), Arg("AccessorDataPointer","mdata")) diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/base_conversion_pack_updates.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/base_conversion_pack_updates.py index e13942ec6..752db3ffc 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/base_conversion_pack_updates.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/base_conversion_pack_updates.py @@ -9,13 +9,28 @@ class BaseConversionPackUpdates: self._update_funcs = {} self._funcsig_mappings = [] self._all_function_arg_mappings = {} - self._include_files = [] + self._header_includes = [] + self._source_includes = [] + self._data_member_mappings = { + DataMember("const char*", "cclass->name"): DataMember("std::string", "name_"), + } + self._all_function_struct_member_access_mappings = {} - def add_funcsig_mappings_to_conversion_data(self, conversion_data): + def add_accessor_wide_conversion_data(self, conversion_data): for mapping in self._funcsig_mappings: debug.line("add_funcsig_mappings_to_conversion_data", f"Adding funcsig mapping: [{mapping.cfuncsig.name}] -> [{mapping.cppfuncsig.name}]") conversion_data.add_global_funcsig_mapping(mapping) + for cmember, cppmember in self._data_member_mappings.items(): + conversion_data.add_data_member_mapping(cmember, cppmember) + + for entry in self._header_includes: + conversion_data.info.add_header_include(entry) + + for entry in self._source_includes: + conversion_data.info.add_source_include(entry) + + # Use this entry point to call the appropriate derived function def apply_updates_for_cfunction(self, cfuncname, conversion_pack): @@ -29,13 +44,14 @@ class BaseConversionPackUpdates: # Override to set the same update for all functions # NOTE: Doesn't apply to global definition def apply_updates_for_all_functions(self, conversion_pack): - # Default data member mappings - for cmember, cppmember in { - DataMember("grib_accessor_class**", "cclass->super"): DataMember("AccessorData", conversion_pack.conversion_data.info.super_class_name), - DataMember("const char*", "cclass->name"): DataMember("std::string", "name_"), - }.items(): - conversion_pack.conversion_data.add_data_member_mapping(cmember, cppmember) + # Add super class as data member + conversion_pack.conversion_data.add_data_member_mapping(DataMember("grib_accessor_class**", "cclass->super"), + DataMember("AccessorData", + conversion_pack.conversion_data.info.super_class_name)) # All function arg mappings for carg, cpparg in self._all_function_arg_mappings.items(): conversion_pack.conversion_data.add_funcbody_arg_mapping(carg, cpparg) + + for cstruct_member_access, cppstruct_member_access in self._all_function_struct_member_access_mappings.items(): + conversion_pack.conversion_data.add_struct_member_access_mapping(cstruct_member_access, cppstruct_member_access) diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/bufr_data_element_conversion_pack_updates.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/bufr_data_element_conversion_pack_updates.py new file mode 100755 index 000000000..d03bb0c31 --- /dev/null +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/bufr_data_element_conversion_pack_updates.py @@ -0,0 +1,29 @@ + +import utils.debug as debug +import grib_accessor.grib_accessor_conversion_pack.conversion_pack_updates.base_conversion_pack_updates as base_conversion_pack_updates +from code_object.arg import Arg +from code_object_converter.conversion_pack.funcsig_mapping import FuncSigMapping +from code_object_converter.conversion_pack.arg_indexes import ArgIndexes +from code_object.funcsig import FuncSig +from code_object.code_interface import NONE_VALUE +from code_object.data_member import DataMember +from code_object.struct_member_access import struct_member_access_from_string + +class BufrDataElementConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates): + def __init__(self) -> None: + super().__init__() + + self._header_includes.extend([ + "GribCpp/BufrDefs.h", + ]) + + self._data_member_mappings.update({ + DataMember("bufr_descriptors_array*", "descriptors"): DataMember("BufrDescriptorsArray", "descriptors"), + }) + + self._all_function_struct_member_access_mappings.update({ + struct_member_access_from_string("creator.op") : struct_member_access_from_string("creator.op_"), + struct_member_access_from_string("creator.name_space") : struct_member_access_from_string("creator.nameSpace_"), + struct_member_access_from_string("creator.set") : struct_member_access_from_string("creator.set_"), + struct_member_access_from_string("creator.name") : struct_member_access_from_string("creator.name_"), + }) diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/closest_date_conversion_pack_updates.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/closest_date_conversion_pack_updates.py index ac21a6ca8..955a2eb76 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/closest_date_conversion_pack_updates.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/closest_date_conversion_pack_updates.py @@ -11,6 +11,6 @@ class ClosestDateConversionPackUpdates(base_conversion_pack_updates.BaseConversi def __init__(self) -> None: super().__init__() - self._include_files.extend([ + self._source_includes.extend([ "", ]) diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/apply_boustrophedonic_conversion_pack_updates.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/data_apply_boustrophedonic_conversion_pack_updates.py similarity index 51% rename from src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/apply_boustrophedonic_conversion_pack_updates.py rename to src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/data_apply_boustrophedonic_conversion_pack_updates.py index 3a31d577c..e2ebd6236 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/apply_boustrophedonic_conversion_pack_updates.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/conversion_pack_updates/data_apply_boustrophedonic_conversion_pack_updates.py @@ -7,13 +7,32 @@ from code_object_converter.conversion_pack.arg_indexes import ArgIndexes from code_object.funcsig import FuncSig from code_object.code_interface import NONE_VALUE -class ApplyBoustrophedonicConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates): +class DataApplyBoustrophedonicConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates): def __init__(self) -> None: super().__init__() + self._update_funcs.update({ + "unpack_helper": self.apply_updates_for_unpack_helper, + "pack_double": self.apply_updates_for_pack_double, + }) + self._funcsig_mappings.extend([ # template static int unpack_helper(grib_accessor* a, T* val, size_t* len) FuncSigMapping(FuncSig("int", "unpack_helper", [Arg("grib_accessor*", "a"), Arg("T*", "val"), Arg("size_t*", "len")]), FuncSig("GribStatus", "unpackHelper", [NONE_VALUE, Arg("std::vector&", "vecTValues"), NONE_VALUE]), ArgIndexes(cbuffer=1, clength=2, cpp_container=1)), ]) + + def apply_updates_for_unpack_helper(self, conversion_pack): + for key,value in { + Arg("double*","pvalues") : Arg("double*","pvalues"), + Arg("T*","pval") : Arg("T*","pval"), + }.items(): + conversion_pack.conversion_data.add_funcbody_arg_mapping(key, value) + + def apply_updates_for_pack_double(self, conversion_pack): + for key,value in { + Arg("double*","pvalues") : Arg("double*","pvalues"), + Arg("double*","pval") : Arg("const double*","pval"), + }.items(): + conversion_pack.conversion_data.add_funcbody_arg_mapping(key, value) diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py index eda5879a1..211c4a26b 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py @@ -7,6 +7,7 @@ import code_object.code_objects as code_objects import code_object.compound_statement as compound_statement import code_object.variable_declaration as variable_declaration import code_object.binary_operation as binary_operation +import code_object.unary_operation as unary_operation import code_object.value_declaration_reference as value_declaration_reference import code_object.if_statement as if_statement import code_object.virtual_member_function as virtual_member_function @@ -133,14 +134,14 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv # If we're calling grib_XXX which is a virtual member function, and the first argument is "a", then we're actually calling ourself! if cfunction_call.name.startswith("grib_"): updated_cfuncname = cfunction_call.name[5:] - if self._conversion_data.is_virtual_member_function(updated_cfuncname) and \ - len(cfunction_call.args) > 0 and cfunction_call.args[0].as_string() == "a": - mapping = self._conversion_data.funcsig_mapping_for_cfuncname(updated_cfuncname) - if mapping: - updated_cppfunction_call = function_call.FunctionCall(mapping.cppfuncsig.name, cppfunction_call.args[1:]) - updated_cppfunction_call = self.validate_function_call_args(updated_cppfunction_call, mapping.cppfuncsig) - debug.line("apply_special_function_call_conversions", f"Updated C++ function call=[{debug.as_debug_string(cppfunction_call)}] to [{debug.as_debug_string(updated_cppfunction_call)}]") - return updated_cppfunction_call + if self._conversion_data.is_virtual_member_function(updated_cfuncname): + if len(cfunction_call.args) > 0 and cfunction_call.args[0].as_string() in ["a"]: + mapping = self._conversion_data.funcsig_mapping_for_cfuncname(updated_cfuncname) + if mapping: + updated_cppfunction_call = function_call.FunctionCall(mapping.cppfuncsig.name, cppfunction_call.args[1:]) + updated_cppfunction_call = self.validate_function_call_args(updated_cppfunction_call, mapping.cppfuncsig) + debug.line("apply_special_function_call_conversions", f"Updated C++ function call=[{debug.as_debug_string(cppfunction_call)}] to [{debug.as_debug_string(updated_cppfunction_call)}]") + return updated_cppfunction_call for cfuncname, cppfuncname in special_function_name_mapping.items(): if cfunction_call.name == cfuncname: @@ -152,13 +153,15 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv return None def validate_variable_declaration(self, cvariable_declaration, cppvariable_declaration): - if "GribStatus" in cppvariable_declaration.variable.as_string() and \ - not isinstance(cppvariable_declaration.value, function_call.FunctionCall) and \ - not cppvariable_declaration.value.as_string().startswith("GribStatus"): - updated_cpp_variable_declaration = variable_declaration.VariableDeclaration( - cppvariable_declaration.variable, - literal.Literal(f"GribStatus{{{cppvariable_declaration.value.as_string()}}}")) - return updated_cpp_variable_declaration + if "GribStatus" in cppvariable_declaration.variable.as_string(): + if not (isinstance(cppvariable_declaration.value, function_call.FunctionCall) or + cppvariable_declaration.value.as_string().startswith("GribStatus") or + cppvariable_declaration.value.as_string() == "{}"): + debug.line("validate_binary_operation", f"GribStatus variable [{debug.as_debug_string(cppvariable_declaration.variable)}] is assigned incorrect value type [{debug.as_debug_string(cppvariable_declaration.value)}] - updating") + updated_cpp_variable_declaration = variable_declaration.VariableDeclaration( + cppvariable_declaration.variable, + literal.Literal(f"GribStatus{{{cppvariable_declaration.value.as_string()}}}")) + return updated_cpp_variable_declaration return super().validate_variable_declaration(cvariable_declaration, cppvariable_declaration) @@ -178,9 +181,9 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv if isinstance(cppright, cast_expression.CastExpression): cpp_right_expression = cppright.expression - if isinstance(cpp_right_expression, function_call.FunctionCall) and cpp_right_expression.name in ["gribContextMalloc", "gribContextRealloc"]: + if isinstance(cpp_right_expression, function_call.FunctionCall) and cpp_right_expression.name in ["gribContextMalloc", "gribContextMallocClear", "gribContextRealloc"]: # For now, we'll assume we're allocating a container (may need to revisit) - cpp_alloc = literal.Literal(f"{arg_utils.extract_name(cppleft)}.resize({cpp_right_expression.arg_string});") + cpp_alloc = literal.Literal(f"{arg_utils.extract_name(cppleft)}.resize({strip_semicolon(cpp_right_expression.arg_string)});") debug.line("validate_binary_operation", f"Changed allocation operation from=[{debug.as_debug_string(cppbinary_operation)}] to [{debug.as_debug_string(cpp_alloc)}]") return cpp_alloc @@ -192,7 +195,7 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv expression_value = cppif_statement.expression.as_string() cpparg = self._conversion_data.funcbody_cpparg_for_carg_name(expression_value) if cpparg and cpparg != NONE_VALUE and cpparg.decl_spec.type == "GribStatus": - updated_expression = literal.Literal(f"isError({cpparg.name})") + updated_expression = literal.Literal(f"GribStatusSuccess({cpparg.name})") updated_cppif_statement = if_statement.IfStatement(updated_expression, cppif_statement.action) debug.line("validate_if_statement", f"updated_cppif_statement=[{debug.as_debug_string(updated_cppif_statement)}]") return updated_cppif_statement @@ -274,3 +277,25 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv return super().is_cppfunction_returning_container(cppfunc_object) + def try_to_make_boolean(self, cppcode_object): + + if isinstance(cppcode_object, unary_operation.UnaryOperation): + cpparg = arg_utils.to_cpparg(cppcode_object.operand, self._conversion_data) + if cpparg: + if cpparg.decl_spec.type == "GribStatus": + if cppcode_object.unary_op.value == "!": + updated_expression = literal.Literal(f"GribStatusSuccess({cpparg.name})") + else: + updated_expression = literal.Literal(f"!GribStatusSuccess({cpparg.name})") + + debug.line("apply_special_unary_operation_conversion", f"Updating GribStatus error: [{debug.as_debug_string(cppcode_object)}]->[{debug.as_debug_string(updated_expression)}]") + return updated_expression + + if isinstance(cppcode_object, function_call.FunctionCall): + cppfuncsig = self._conversion_data.cppfuncsig_for_cppfuncname(cppcode_object.name) + if cppfuncsig: + if cppfuncsig.return_type.type == "GribStatus": + updated_cppcode_object = literal.Literal(f"GribStatusSuccess({cppcode_object.as_string()})") + return updated_cppcode_object + + return super().try_to_make_boolean(cppcode_object) \ No newline at end of file diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/data_shsimple_packing_validation.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/data_shsimple_packing_validation.py new file mode 100755 index 000000000..84ccab975 --- /dev/null +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/data_shsimple_packing_validation.py @@ -0,0 +1,24 @@ + +import utils.debug as debug +import grib_accessor.grib_accessor_conversion_pack.grib_accessor_conversion_validation as grib_accessor_conversion_validation +import code_object_converter.conversion_pack.arg_utils as arg_utils +import code_object.literal as literal +from code_object_converter.conversion_utils import as_commented_out_code + +class DataShsimplePackingValidation(grib_accessor_conversion_validation.GribAccessorConversionValidation): + + def validate_unary_operation(self, cunary_operation, cppunary_operation): + if self._conversion_data.current_cfuncname == "pack_double": + if cppunary_operation.as_string() == "doubleValues++;": + return as_commented_out_code(cppunary_operation, f"Removed invalid unary operation - will handle in next function call") + + return super().validate_unary_operation(cunary_operation, cppunary_operation) + + def validate_function_call(self, cfunction_call, cppfunction_call): + + if self._conversion_data.current_cfuncname == "pack_double": + if cppfunction_call.name == "gribSetDouble": + if cppfunction_call.args[0].as_string() == "codedValues_": + cppfunction_call.args[1] = literal.Literal("doubleValues[1]") + + return super().validate_function_call(cfunction_call, cppfunction_call) \ No newline at end of file diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/section_pointer_validation.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/section_pointer_validation.py new file mode 100755 index 000000000..1c9752c27 --- /dev/null +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/validators/section_pointer_validation.py @@ -0,0 +1,14 @@ + +import utils.debug as debug +import grib_accessor.grib_accessor_conversion_pack.grib_accessor_conversion_validation as grib_accessor_conversion_validation +import code_object_converter.conversion_pack.arg_utils as arg_utils + +class SectionPointerValidation(grib_accessor_conversion_validation.GribAccessorConversionValidation): + + def validate_cast_expression(self, ccast_expression, cppcast_expression): + if self._conversion_data.current_cfuncname == "init": + # We don't need either cast expression in the constructor, so remove them! + debug.line("validate_cast_expression", f"[init()] Removing cast expression: [{debug.as_debug_string(cppcast_expression)}]->[{debug.as_debug_string(cppcast_expression.expression)}]") + return cppcast_expression.expression + + return super().validate_cast_expression(ccast_expression, cppcast_expression) \ No newline at end of file diff --git a/src/clang_convert/grib_accessor/j2/grib_accessor_header.h.j2 b/src/clang_convert/grib_accessor/j2/grib_accessor_header.h.j2 index c3f92738c..80089e851 100644 --- a/src/clang_convert/grib_accessor/j2/grib_accessor_header.h.j2 +++ b/src/clang_convert/grib_accessor/j2/grib_accessor_header.h.j2 @@ -12,7 +12,7 @@ {% for i in c.header_file_includes -%} #include "{{ i }}" -{%- endfor %} +{% endfor %} namespace {{ c.nested_namespaces }} { diff --git a/src/clang_convert/grib_accessor/supporting/data_member_mappings.py b/src/clang_convert/grib_accessor/supporting/data_member_mappings.py index c3193e5b2..053706dd7 100755 --- a/src/clang_convert/grib_accessor/supporting/data_member_mappings.py +++ b/src/clang_convert/grib_accessor/supporting/data_member_mappings.py @@ -23,8 +23,13 @@ grib_accessor_base_data_members_map = { DataMember("grib_accessor*","attributes") : DataMember("std::vector","attributes_"), # grib_handle conversion helpers DataMember("grib_loader*","loader") : DataMember("AccessorLoaderPtr","loader()"), - DataMember("char*","gts_header") : DataMember("std::string","gtsHeader"), - DataMember("size_t","gts_header_len") : DataMember("std::string","gtsHeader"), + DataMember("int","partial") : DataMember("int","partial_"), + DataMember("int","header_mode") : DataMember("int","headerMode_"), + DataMember("char*","gts_header") : DataMember("std::string","gtsHeader_"), + DataMember("size_t","gts_header_len") : DataMember("std::string","gtsHeader_"), + DataMember("char*","section_offset") : DataMember("std::vector","sectionOffsetList_"), + DataMember("char*","section_length") : DataMember("std::vector","sectionLengthList_"), + DataMember("int","sections_count") : DataMember("std::vector","sectionsCount_"), } def add_data_member_mappings_to_conversion_data(conversion_data): diff --git a/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_buffer_stub_funcsig_mappings.py b/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_buffer_stub_funcsig_mappings.py index 7f68bcd3e..260dbf20b 100755 --- a/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_buffer_stub_funcsig_mappings.py +++ b/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_buffer_stub_funcsig_mappings.py @@ -10,7 +10,7 @@ grib_buffer_stub_funcsig_mappings = [ FuncSig("void", "griBufferDelete", [NONE_VALUE, Arg("AccessorDataBuffer&", "b")])), FuncSigMapping( FuncSig("void", "grib_buffer_replace", [Arg("grib_accessor*", "a"), Arg("const unsigned char*", "data"), Arg("size_t", "newsize"), Arg("int", "update_lengths"), Arg("int", "update_paddings")]), - FuncSig("void", "gribBufferReplace", [NONE_VALUE, Arg("AccessorDataBuffer&", "data"), Arg("size_t", "newsize"), Arg("int", "updateLengths"), Arg("int", "updatePaddings")])), + FuncSig("void", "gribBufferReplace", [NONE_VALUE, Arg("const AccessorDataBuffer&", "data"), Arg("size_t", "newsize"), Arg("int", "updateLengths"), Arg("int", "updatePaddings")])), FuncSigMapping( FuncSig("void", "grib_buffer_set_ulength_bits", [Arg("const grib_context*", "c"), Arg("grib_buffer*", "b"), Arg("size_t", "length_bits")]), FuncSig("void", "gribBufferSetUlengthBits", [NONE_VALUE, Arg("AccessorDataBuffer&", "b"), Arg("size_t", "lengthBits")])), diff --git a/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_value_stub_funcsig_mappings.py b/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_value_stub_funcsig_mappings.py index 71b5eb0c3..7e6c0a011 100755 --- a/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_value_stub_funcsig_mappings.py +++ b/src/clang_convert/grib_accessor/supporting/funcsig_mappings/grib_stub_funcsig_mappings/grib_value_stub_funcsig_mappings.py @@ -20,5 +20,8 @@ grib_value_stub_funcsig_mappings = [ FuncSigMapping( FuncSig("int", "grib_get_nearest_smaller_value", [Arg("grib_handle*", "h"), Arg("const char*", "name"), Arg("double", "val"), Arg("double*", "nearest")]), FuncSig("GribStatus", "gribGetNearestSmallerValue", [NONE_VALUE, Arg("AccessorName const&", "name"), Arg("double", "val"), Arg("double&", "nearest")])), + + FuncSigMapping( FuncSig("int", "grib_is_missing", [Arg("grib_handle*", "h"), Arg("const char*", "name"), Arg("int*", "err")]), + FuncSig("GribStatus", "gribIsMissing", [NONE_VALUE, Arg("AccessorName", "name"), Arg("int", "err")])), ] diff --git a/src/clang_convert/grib_accessor/supporting/type_mappings.py b/src/clang_convert/grib_accessor/supporting/type_mappings.py index 95661912e..57cfba300 100755 --- a/src/clang_convert/grib_accessor/supporting/type_mappings.py +++ b/src/clang_convert/grib_accessor/supporting/type_mappings.py @@ -7,6 +7,7 @@ from code_object.code_interface import NONE_VALUE # ==================== FUNCSIG TYPE MAPPINGS: Begin ==================== common_funcsig_type_mappings = { + #"grib_accessor*" : "AccessorDataPtr", "char*" : "std::string&", "char[]" : "std::string&", } @@ -23,13 +24,14 @@ def add_funcsig_type_mappings_to_conversion_data(conversion_data): # ==================== FUNCBODY TYPE MAPPINGS: Begin ==================== common_grib_funcbody_type_mappings = { - "grib_accessor*" : "AccessorPtr", - "grib_accessor_class*" : NONE_VALUE, - "grib_handle*" : NONE_VALUE, - "grib_context*" : NONE_VALUE, - "grib_expression*" : "GribExpressionPtr", - "grib_codetable*" : "GribCodeTablePtr", - "grib_action*" : "GribActionPtr" + "grib_accessor*" : "AccessorPtr", + "grib_accessor_class*" : NONE_VALUE, + "grib_handle*" : NONE_VALUE, + "grib_context*" : NONE_VALUE, + "grib_expression*" : "GribExpressionPtr", + "grib_codetable*" : "GribCodeTablePtr", + "grib_action*" : "GribActionPtr", + "bufr_descriptors_array" : "BufrDescriptorsArray", } grib_array_funcbody_type_mappings = { diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt index 7a832723e..3d425f10d 100644 --- a/src/cpp/CMakeLists.txt +++ b/src/cpp/CMakeLists.txt @@ -53,6 +53,7 @@ set(accessor_utils_src_files ) set(accessor_grib_cpp_src_files + ${accessor_grib_cpp_dir}/BufrDefs.h ${accessor_grib_cpp_dir}/GribCppIncludes.h ${accessor_grib_cpp_dir}/GribBits.cc ${accessor_grib_cpp_dir}/GribBits.h diff --git a/src/cpp/eccodes/accessor/AccessorData/AccessorData.h b/src/cpp/eccodes/accessor/AccessorData/AccessorData.h index ac6d0a6b1..cf174a384 100644 --- a/src/cpp/eccodes/accessor/AccessorData/AccessorData.h +++ b/src/cpp/eccodes/accessor/AccessorData/AccessorData.h @@ -96,6 +96,12 @@ protected: // Conversion helpers... std::vector attributes_; + int partial_{}; + int headerMode_{}; + std::string gtsHeader_; + std::vector sectionOffsetList_; + std::vector sectionLengthList_; + std::vector sectionsCount_; }; template diff --git a/src/cpp/eccodes/accessor/GribCpp/BufrDefs.h b/src/cpp/eccodes/accessor/GribCpp/BufrDefs.h new file mode 100644 index 000000000..06a81348e --- /dev/null +++ b/src/cpp/eccodes/accessor/GribCpp/BufrDefs.h @@ -0,0 +1,79 @@ +#pragma once + +#include "AccessorDefs.h" + +#include +#include + +namespace eccodes::accessor { + +/* types of BUFR descriptors used in bufr_descriptor->type*/ + +enum class BufrDescriptorType{ + UNKNOWN, + STRING, + DOUBLE, + LONG, + TABLE, + FLAG, + REPLICATION, + OPERATOR, + SEQUENCE, + + // Used for conversion routines - keep last! + ENUMSIZE +}; + +constexpr int toInt(BufrDescriptorType type) { + return static_cast(type); +} + +//std::string toString(GribType type); +//GribType toGribType(std::string_view type); + +struct BufrDescriptor +{ + //grib_context* context; + long code; + int F; + int X; + int Y; + int type; + /*char* name; Not needed: All usage commented out. See ECC-489 */ + std::string shortName; + std::string units; + long scale; + double factor; + long reference; + long width; + int nokey; /* set if descriptor does not have an associated key */ + AccessorPtr a; //grib_accessor* a; +}; + +struct BufrDescriptorsArray +{ + std::vector> v; + size_t size; + size_t n; + size_t incsize; + size_t number_of_pop_front; + //grib_context* context; +}; + +struct bufr_descriptors_map_list +{ + std::vector unexpanded; + std::vector expanded; + bufr_descriptors_map_list* next; +}; + +/* BUFR: Operator 203YYY: Linked list storing Table B changed reference values */ +struct BufrTablebOverride +{ + BufrTablebOverride* next; + int code; + long newRefVal; +}; + + +} diff --git a/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc b/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc index c16adb2e9..2e3593825 100644 --- a/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc +++ b/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc @@ -3,9 +3,9 @@ namespace eccodes::accessor { // Helper for the conversion process -bool isError(GribStatus stat) +bool GribStatusSuccess(GribStatus stat) { - return stat != GribStatus::SUCCESS; + return stat == GribStatus::SUCCESS; } } diff --git a/src/cpp/eccodes/accessor/GribCpp/GribStatus.h b/src/cpp/eccodes/accessor/GribCpp/GribStatus.h index e2a663883..2475b74de 100644 --- a/src/cpp/eccodes/accessor/GribCpp/GribStatus.h +++ b/src/cpp/eccodes/accessor/GribCpp/GribStatus.h @@ -86,6 +86,6 @@ enum class GribStatus{ }; // Helper for the conversion process -bool isError(GribStatus stat); +bool GribStatusSuccess(GribStatus stat); } diff --git a/src/cpp/eccodes/accessor/GribStub/GribActionStub.h b/src/cpp/eccodes/accessor/GribStub/GribActionStub.h index a3a3f5bcb..11ffed142 100644 --- a/src/cpp/eccodes/accessor/GribStub/GribActionStub.h +++ b/src/cpp/eccodes/accessor/GribStub/GribActionStub.h @@ -13,9 +13,9 @@ struct GribAction std::string op_; std::string nameSpace_; unsigned long flags_; - //char* defaultkey; /** name of the key used as default if not found */ + std::string defaultkey; /** name of the key used as default if not found */ //grib_arguments* default_value; /** default expression as in .def file */ - //char* set; + std::string set; //char* debug_info; /** purely for debugging and tracing */ }; diff --git a/src/cpp/eccodes/accessor/GribStub/GribBufferStub.cc b/src/cpp/eccodes/accessor/GribStub/GribBufferStub.cc index cc7ddfb72..16499092c 100644 --- a/src/cpp/eccodes/accessor/GribStub/GribBufferStub.cc +++ b/src/cpp/eccodes/accessor/GribStub/GribBufferStub.cc @@ -10,7 +10,7 @@ void griBufferDelete(AccessorDataBuffer& b) assert(false); } -void gribBufferReplace(AccessorDataBuffer& data, size_t newsize, int update_lengths, int update_paddings) +void gribBufferReplace(const AccessorDataBuffer& data, size_t newsize, int update_lengths, int update_paddings) { assert(false); } diff --git a/src/cpp/eccodes/accessor/GribStub/GribBufferStub.h b/src/cpp/eccodes/accessor/GribStub/GribBufferStub.h index bdacd0371..b60a8a1df 100644 --- a/src/cpp/eccodes/accessor/GribStub/GribBufferStub.h +++ b/src/cpp/eccodes/accessor/GribStub/GribBufferStub.h @@ -8,7 +8,7 @@ namespace eccodes::accessor { void griBufferDelete(AccessorDataBuffer& b); -void gribBufferReplace(AccessorDataBuffer& data, size_t newsize, int updateLengths, int updatePaddings); +void gribBufferReplace(const AccessorDataBuffer& data, size_t newsize, int updateLengths, int updatePaddings); void gribBufferSetUlengthBits(AccessorDataBuffer& b, size_t lengthBits); AccessorDataBuffer gribCreateGrowableBuffer(); diff --git a/src/cpp/eccodes/accessor/GribStub/GribValueStub.cc b/src/cpp/eccodes/accessor/GribStub/GribValueStub.cc index 408231e5c..c8e64952a 100644 --- a/src/cpp/eccodes/accessor/GribStub/GribValueStub.cc +++ b/src/cpp/eccodes/accessor/GribStub/GribValueStub.cc @@ -34,4 +34,10 @@ GribStatus gribGetNearestSmallerValue(AccessorName name, double val, double& nea return GribStatus::NOT_IMPLEMENTED; } +GribStatus gribIsMissing(AccessorName name, GribStatus& err) +{ + assert(false); + return GribStatus::NOT_IMPLEMENTED; +} + } diff --git a/src/cpp/eccodes/accessor/GribStub/GribValueStub.h b/src/cpp/eccodes/accessor/GribStub/GribValueStub.h index d33fa143b..d5f2baf63 100644 --- a/src/cpp/eccodes/accessor/GribStub/GribValueStub.h +++ b/src/cpp/eccodes/accessor/GribStub/GribValueStub.h @@ -16,4 +16,5 @@ GribStatus gribGetDoubleElementSet(AccessorName const& name, const std::vector indexArray, size_t len, std::vector& valArray); GribStatus gribGetNearestSmallerValue(AccessorName name, double val, double& nearest); +GribStatus gribIsMissing(AccessorName name, GribStatus& err); } \ No newline at end of file