From 8991b936a7fa97e7909470516ba7908b4b693970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Wed, 9 Oct 2024 01:05:53 +0200 Subject: [PATCH 1/7] Add tests for parse/list_of_primitives --- .../int/expected_symbol_table.txt | 33 +++++++++++++++++++ .../list_of_primitives/int/meta_model.py | 11 +++++++ .../string/expected_symbol_table.txt | 33 +++++++++++++++++++ .../list_of_primitives/string/meta_model.py | 11 +++++++ 4 files changed, 88 insertions(+) create mode 100644 test_data/parse/expected/list_of_primitives/int/expected_symbol_table.txt create mode 100644 test_data/parse/expected/list_of_primitives/int/meta_model.py create mode 100644 test_data/parse/expected/list_of_primitives/string/expected_symbol_table.txt create mode 100644 test_data/parse/expected/list_of_primitives/string/meta_model.py diff --git a/test_data/parse/expected/list_of_primitives/int/expected_symbol_table.txt b/test_data/parse/expected/list_of_primitives/int/expected_symbol_table.txt new file mode 100644 index 000000000..1691513cf --- /dev/null +++ b/test_data/parse/expected/list_of_primitives/int/expected_symbol_table.txt @@ -0,0 +1,33 @@ +UnverifiedSymbolTable( + our_types=[ + ConcreteClass( + name='Something', + is_implementation_specific=False, + inheritances=[], + properties=[ + Property( + name='something', + type_annotation=SubscriptedTypeAnnotation( + identifier='List', + subscripts=[ + AtomicTypeAnnotation( + identifier='int', + node=...)], + node=...), + description=None, + node=...)], + methods=[], + invariants=[], + serialization=None, + description=Description( + document=..., + node=...), + node=..., + properties_by_name=..., + methods_by_name=...)], + constants=[], + verification_functions=[], + meta_model=MetaModel( + description=None, + version='dummy', + xml_namespace='https://dummy.com')) \ No newline at end of file diff --git a/test_data/parse/expected/list_of_primitives/int/meta_model.py b/test_data/parse/expected/list_of_primitives/int/meta_model.py new file mode 100644 index 000000000..f65d61fb8 --- /dev/null +++ b/test_data/parse/expected/list_of_primitives/int/meta_model.py @@ -0,0 +1,11 @@ +class Something: + """ + Represent something. + + Indented. + """ + something: List[int] + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" diff --git a/test_data/parse/expected/list_of_primitives/string/expected_symbol_table.txt b/test_data/parse/expected/list_of_primitives/string/expected_symbol_table.txt new file mode 100644 index 000000000..4a9d8664c --- /dev/null +++ b/test_data/parse/expected/list_of_primitives/string/expected_symbol_table.txt @@ -0,0 +1,33 @@ +UnverifiedSymbolTable( + our_types=[ + ConcreteClass( + name='Something', + is_implementation_specific=False, + inheritances=[], + properties=[ + Property( + name='something', + type_annotation=SubscriptedTypeAnnotation( + identifier='List', + subscripts=[ + AtomicTypeAnnotation( + identifier='str', + node=...)], + node=...), + description=None, + node=...)], + methods=[], + invariants=[], + serialization=None, + description=Description( + document=..., + node=...), + node=..., + properties_by_name=..., + methods_by_name=...)], + constants=[], + verification_functions=[], + meta_model=MetaModel( + description=None, + version='dummy', + xml_namespace='https://dummy.com')) \ No newline at end of file diff --git a/test_data/parse/expected/list_of_primitives/string/meta_model.py b/test_data/parse/expected/list_of_primitives/string/meta_model.py new file mode 100644 index 000000000..36f159e7c --- /dev/null +++ b/test_data/parse/expected/list_of_primitives/string/meta_model.py @@ -0,0 +1,11 @@ +class Something: + """ + Represent something. + + Indented. + """ + something: List[str] + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" From d2f768d90ca0515a2d5ac4165ef936fe9a1cb689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Thu, 10 Oct 2024 11:22:58 +0200 Subject: [PATCH 2/7] Add test for type missmatch between constructor and property --- .../type_missmatch/expected_error.txt | 1 + .../type_missmatch/meta_model.py | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/expected_error.txt create mode 100644 test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py diff --git a/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/expected_error.txt b/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/expected_error.txt new file mode 100644 index 000000000..14db0c0d5 --- /dev/null +++ b/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/expected_error.txt @@ -0,0 +1 @@ +The constructor argument 'x' and the property 'x' for the class 'SomeContainerClass' mismatch in type. The argument is typed as List[int] while the property is typed as List[str]. We expect the constructors and the properties to match in type. \ No newline at end of file diff --git a/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py b/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py new file mode 100644 index 000000000..f3c3efa79 --- /dev/null +++ b/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py @@ -0,0 +1,9 @@ +class SomeContainerClass: + x: List[str] + + def __init__(self, x: List[int]) -> None: + self.x = x + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" From a63c8a0f2385c0829c8f20cd6c11f81cc73aaa7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Thu, 10 Oct 2024 11:25:56 +0200 Subject: [PATCH 3/7] Intermediate: allow list of primitives --- aas_core_codegen/intermediate/_translate.py | 9 +- .../{ => class}/expected_symbol_table.txt | 0 .../subscripted/{ => class}/meta_model.py | 0 .../primitive/expected_symbol_table.txt | 85 +++++++++++++++++++ .../subscripted/primitive/meta_model.py | 9 ++ 5 files changed, 100 insertions(+), 3 deletions(-) rename test_data/intermediate/expected/type_annotation/subscripted/{ => class}/expected_symbol_table.txt (100%) rename test_data/intermediate/expected/type_annotation/subscripted/{ => class}/meta_model.py (100%) create mode 100644 test_data/intermediate/expected/type_annotation/subscripted/primitive/expected_symbol_table.txt create mode 100644 test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py diff --git a/aas_core_codegen/intermediate/_translate.py b/aas_core_codegen/intermediate/_translate.py index d9d316786..34499225d 100644 --- a/aas_core_codegen/intermediate/_translate.py +++ b/aas_core_codegen/intermediate/_translate.py @@ -4415,9 +4415,12 @@ def _verify_only_simple_type_patterns(symbol_table: SymbolTable) -> List[Error]: type_anno = beneath_optional(prop.type_annotation) if isinstance(type_anno, ListTypeAnnotation): if not ( - isinstance(type_anno.items, OurTypeAnnotation) - and isinstance( + isinstance(type_anno.items, PrimitiveTypeAnnotation) + or ( + isinstance(type_anno.items, OurTypeAnnotation) + and isinstance( type_anno.items.our_type, (AbstractClass, ConcreteClass) + ) ) ): errors.append( @@ -4425,7 +4428,7 @@ def _verify_only_simple_type_patterns(symbol_table: SymbolTable) -> List[Error]: prop.parsed.node, f"We currently support only a limited set of " f"type annotation patterns. At the moment, we handle " - f"only lists of classes (both concrete or abstract), " + f"only lists of classes (both concrete or abstract) or primitive types, " f"but the property {prop.name!r} " f"of the class {cls.name!r} " f"has type: {prop.type_annotation}. " diff --git a/test_data/intermediate/expected/type_annotation/subscripted/expected_symbol_table.txt b/test_data/intermediate/expected/type_annotation/subscripted/class/expected_symbol_table.txt similarity index 100% rename from test_data/intermediate/expected/type_annotation/subscripted/expected_symbol_table.txt rename to test_data/intermediate/expected/type_annotation/subscripted/class/expected_symbol_table.txt diff --git a/test_data/intermediate/expected/type_annotation/subscripted/meta_model.py b/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py similarity index 100% rename from test_data/intermediate/expected/type_annotation/subscripted/meta_model.py rename to test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py diff --git a/test_data/intermediate/expected/type_annotation/subscripted/primitive/expected_symbol_table.txt b/test_data/intermediate/expected/type_annotation/subscripted/primitive/expected_symbol_table.txt new file mode 100644 index 000000000..409ed86fb --- /dev/null +++ b/test_data/intermediate/expected/type_annotation/subscripted/primitive/expected_symbol_table.txt @@ -0,0 +1,85 @@ +SymbolTable( + our_types=[ + ConcreteClass( + name='SomeContainerClass', + inheritances=[], + inheritance_id_set=..., + ancestors=[], + ancestor_id_set=..., + is_implementation_specific=False, + interface=None, + descendant_id_set=..., + descendants=[], + concrete_descendant_id_set=..., + concrete_descendants=[], + properties=[ + Property( + name='x', + type_annotation=ListTypeAnnotation( + items=PrimitiveTypeAnnotation( + a_type='STR', + parsed=...), + parsed=...), + description=None, + specified_for='Reference to ConcreteClass SomeContainerClass', + parsed=...)], + methods=[], + constructor=Constructor( + name='__init__', + arguments=[ + Argument( + name='x', + type_annotation=ListTypeAnnotation( + items=PrimitiveTypeAnnotation( + a_type='STR', + parsed=...), + parsed=...), + default=None, + parsed=...)], + returns=None, + description=None, + contracts=Contracts( + preconditions=[], + snapshots=[], + postconditions=[]), + parsed=..., + arguments_by_name=..., + is_implementation_specific=False, + statements=[ + textwrap.dedent("""\ + AssignArgument( + name='x', + argument='x', + default=None)""")], + inlined_statements=[ + textwrap.dedent("""\ + AssignArgument( + name='x', + argument='x', + default=None)""")]), + invariants=[], + serialization=Serialization( + with_model_type=False), + description=None, + parsed=..., + properties_by_name=..., + property_id_set=..., + methods_by_name=..., + method_id_set=..., + invariant_id_set=...)], + our_types_topologically_sorted=[ + 'Reference to our type SomeContainerClass'], + enumerations=[], + constrained_primitives=[], + classes=[ + 'Reference to our type SomeContainerClass'], + concrete_classes=[ + 'Reference to our type SomeContainerClass'], + constants=[], + constants_by_name=..., + verification_functions=[], + verification_functions_by_name=..., + meta_model=MetaModel( + description=None, + version='dummy', + xml_namespace='https://dummy.com')) \ No newline at end of file diff --git a/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py b/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py new file mode 100644 index 000000000..345a02a6c --- /dev/null +++ b/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py @@ -0,0 +1,9 @@ +class SomeContainerClass: + x: List[str] + + def __init__(self, x: List[str]) -> None: + self.x = x + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" From eb8cefb1272949f80b2371adf5fa4ebff6748f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Wed, 13 Nov 2024 00:08:35 +0100 Subject: [PATCH 4/7] JSON Schema generation --- .../expected_output/schema.json | 40 +++++++++++++++++++ .../expected_output/stdout.txt | 1 + .../input/snippets/schema_base.json | 5 +++ .../list_of_primitives/meta_model.py | 16 ++++++++ 4 files changed, 62 insertions(+) create mode 100644 test_data/jsonschema/test_main/list_of_primitives/expected_output/schema.json create mode 100644 test_data/jsonschema/test_main/list_of_primitives/expected_output/stdout.txt create mode 100644 test_data/jsonschema/test_main/list_of_primitives/input/snippets/schema_base.json create mode 100644 test_data/jsonschema/test_main/list_of_primitives/meta_model.py diff --git a/test_data/jsonschema/test_main/list_of_primitives/expected_output/schema.json b/test_data/jsonschema/test_main/list_of_primitives/expected_output/schema.json new file mode 100644 index 000000000..da3d8d0bd --- /dev/null +++ b/test_data/jsonschema/test_main/list_of_primitives/expected_output/schema.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "AssetAdministrationShellEnvironment", + "type": "object", + "$id": "https://dummy.com", + "definitions": { + "ListOfPrimitives": { + "type": "object", + "properties": { + "strings": { + "type": "array", + "items": { + "type": "string" + } + }, + "integers": { + "type": "array", + "items": { + "type": "integer" + } + }, + "booleans": { + "type": "array", + "items": { + "type": "boolean" + } + } + }, + "required": [ + "strings", + "integers", + "booleans" + ] + }, + "ModelType": { + "type": "string", + "enum": [] + } + } +} \ No newline at end of file diff --git a/test_data/jsonschema/test_main/list_of_primitives/expected_output/stdout.txt b/test_data/jsonschema/test_main/list_of_primitives/expected_output/stdout.txt new file mode 100644 index 000000000..2d755fc5a --- /dev/null +++ b/test_data/jsonschema/test_main/list_of_primitives/expected_output/stdout.txt @@ -0,0 +1 @@ +Code generated to: diff --git a/test_data/jsonschema/test_main/list_of_primitives/input/snippets/schema_base.json b/test_data/jsonschema/test_main/list_of_primitives/input/snippets/schema_base.json new file mode 100644 index 000000000..fe668c922 --- /dev/null +++ b/test_data/jsonschema/test_main/list_of_primitives/input/snippets/schema_base.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "AssetAdministrationShellEnvironment", + "type": "object" +} diff --git a/test_data/jsonschema/test_main/list_of_primitives/meta_model.py b/test_data/jsonschema/test_main/list_of_primitives/meta_model.py new file mode 100644 index 000000000..6c446e748 --- /dev/null +++ b/test_data/jsonschema/test_main/list_of_primitives/meta_model.py @@ -0,0 +1,16 @@ +from typing import List + + +class List_of_primitives(): + strings: List[str] + integers: List[int] + booleans: List[bool] + + def __init__(self, strings: List[str], integers: List[int], booleans: List[bool]) -> None: + self.strings = strings + self.integers = integers + self.booleans = booleans + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" From fe08978c0f5e7f21ac06d4f32e5b2c572a70d0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Mon, 3 Feb 2025 16:07:17 +0100 Subject: [PATCH 5/7] Code formatting --- aas_core_codegen/intermediate/_translate.py | 2 +- .../jsonschema/test_main/list_of_primitives/meta_model.py | 6 ++++-- .../parse/expected/list_of_primitives/int/meta_model.py | 1 + .../parse/expected/list_of_primitives/string/meta_model.py | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/aas_core_codegen/intermediate/_translate.py b/aas_core_codegen/intermediate/_translate.py index 34499225d..669c58458 100644 --- a/aas_core_codegen/intermediate/_translate.py +++ b/aas_core_codegen/intermediate/_translate.py @@ -4419,7 +4419,7 @@ def _verify_only_simple_type_patterns(symbol_table: SymbolTable) -> List[Error]: or ( isinstance(type_anno.items, OurTypeAnnotation) and isinstance( - type_anno.items.our_type, (AbstractClass, ConcreteClass) + type_anno.items.our_type, (AbstractClass, ConcreteClass) ) ) ): diff --git a/test_data/jsonschema/test_main/list_of_primitives/meta_model.py b/test_data/jsonschema/test_main/list_of_primitives/meta_model.py index 6c446e748..531303f43 100644 --- a/test_data/jsonschema/test_main/list_of_primitives/meta_model.py +++ b/test_data/jsonschema/test_main/list_of_primitives/meta_model.py @@ -1,12 +1,14 @@ from typing import List -class List_of_primitives(): +class List_of_primitives: strings: List[str] integers: List[int] booleans: List[bool] - def __init__(self, strings: List[str], integers: List[int], booleans: List[bool]) -> None: + def __init__( + self, strings: List[str], integers: List[int], booleans: List[bool] + ) -> None: self.strings = strings self.integers = integers self.booleans = booleans diff --git a/test_data/parse/expected/list_of_primitives/int/meta_model.py b/test_data/parse/expected/list_of_primitives/int/meta_model.py index f65d61fb8..2acc8d822 100644 --- a/test_data/parse/expected/list_of_primitives/int/meta_model.py +++ b/test_data/parse/expected/list_of_primitives/int/meta_model.py @@ -4,6 +4,7 @@ class Something: Indented. """ + something: List[int] diff --git a/test_data/parse/expected/list_of_primitives/string/meta_model.py b/test_data/parse/expected/list_of_primitives/string/meta_model.py index 36f159e7c..c1c359bf5 100644 --- a/test_data/parse/expected/list_of_primitives/string/meta_model.py +++ b/test_data/parse/expected/list_of_primitives/string/meta_model.py @@ -4,6 +4,7 @@ class Something: Indented. """ + something: List[str] From 4f6bbf09295f6bbacbde546f16742fafedeef146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Tue, 4 Feb 2025 13:57:25 +0100 Subject: [PATCH 6/7] Add cpp code generation --- aas_core_codegen/cpp/enhancing/_generate.py | 11 +- aas_core_codegen/cpp/iteration/_generate.py | 24 +- aas_core_codegen/cpp/jsonization/_generate.py | 63 +- .../cpp/verification/_generate.py | 12 +- aas_core_codegen/cpp/visitation/_generate.py | 12 +- aas_core_codegen/cpp/xmlization/_generate.py | 75 +- .../expected_output/common.cpp | 14069 ++++++++++++++++ .../expected_output/common.hpp | 10092 +++++++++++ .../expected_output/constants.cpp | 27 + .../expected_output/constants.hpp | 40 + .../expected_output/enhancing.hpp | 638 + .../expected_output/iteration.cpp | 1229 ++ .../expected_output/iteration.hpp | 338 + .../expected_output/jsonization.cpp | 1587 ++ .../expected_output/jsonization.hpp | 202 + .../expected_output/pattern.cpp | 16 + .../expected_output/pattern.hpp | 36 + .../expected_output/revm.cpp | 863 + .../expected_output/revm.hpp | 215 + .../expected_output/stdout.txt | 1 + .../expected_output/stringification.cpp | 365 + .../expected_output/stringification.hpp | 93 + .../expected_output/types.cpp | 158 + .../expected_output/types.hpp | 253 + .../expected_output/verification.cpp | 727 + .../expected_output/verification.hpp | 225 + .../expected_output/visitation.cpp | 109 + .../expected_output/visitation.hpp | 93 + .../expected_output/wstringification.cpp | 84 + .../expected_output/wstringification.hpp | 65 + .../expected_output/xmlization.cpp | 4718 ++++++ .../expected_output/xmlization.hpp | 290 + .../input/snippets/namespace.txt | 1 + .../list_of_primitives/meta_model.py | 28 + tests/cpp/test_main.py | 62 +- 35 files changed, 36715 insertions(+), 106 deletions(-) create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/common.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/common.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/constants.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/constants.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/enhancing.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/iteration.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/iteration.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/pattern.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/pattern.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/revm.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/revm.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/stdout.txt create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/stringification.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/stringification.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/types.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/types.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/verification.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/verification.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/visitation.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/visitation.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.cpp create mode 100644 test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.hpp create mode 100644 test_data/cpp/test_main/list_of_primitives/input/snippets/namespace.txt create mode 100644 test_data/cpp/test_main/list_of_primitives/meta_model.py diff --git a/aas_core_codegen/cpp/enhancing/_generate.py b/aas_core_codegen/cpp/enhancing/_generate.py index 9ba9f0252..445a2cbb1 100644 --- a/aas_core_codegen/cpp/enhancing/_generate.py +++ b/aas_core_codegen/cpp/enhancing/_generate.py @@ -379,11 +379,12 @@ def _generate_wrap_snippet_for_required_property( else: assert_never(type_anno.our_type) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) or ( + isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-07-07): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " diff --git a/aas_core_codegen/cpp/iteration/_generate.py b/aas_core_codegen/cpp/iteration/_generate.py index 25fb66792..9f0b5e32e 100644 --- a/aas_core_codegen/cpp/iteration/_generate.py +++ b/aas_core_codegen/cpp/iteration/_generate.py @@ -782,11 +782,13 @@ def __init__(self, cls: intermediate.ConcreteClass) -> None: relevant_properties.append(prop) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-09-27): We expect only lists of classes " f"at the moment, but you specified {prop.type_annotation} " @@ -947,11 +949,13 @@ def _generate_iterator_over_cls_execute_implementation( flow.append(yielding_flow.Yield()) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-09-27): We expect only lists of classes " f"at the moment, but you specified {prop.type_annotation} " diff --git a/aas_core_codegen/cpp/jsonization/_generate.py b/aas_core_codegen/cpp/jsonization/_generate.py index b464fcbd2..94caea708 100644 --- a/aas_core_codegen/cpp/jsonization/_generate.py +++ b/aas_core_codegen/cpp/jsonization/_generate.py @@ -741,6 +741,18 @@ def _generate_deserialize_bytearray() -> Stripped: for primitive_type in intermediate.PrimitiveType ) +_PRIMITIVE_TYPE_TO_NATIVE_TYPE = { + intermediate.PrimitiveType.BOOL: "bool", + intermediate.PrimitiveType.INT: "int64_t", + intermediate.PrimitiveType.FLOAT: "double", + intermediate.PrimitiveType.STR: "std::wstring", + intermediate.PrimitiveType.BYTEARRAY: "std::vector", +} +assert all( + primitive_type in _PRIMITIVE_TYPE_TO_NATIVE_TYPE + for primitive_type in intermediate.PrimitiveType +) + def _generate_get_model_type() -> Stripped: """Generate the getter of the model type from JSON object for dispatches.""" @@ -1158,20 +1170,27 @@ def _generate_deserialize_list_property( """ type_anno = intermediate.beneath_optional(prop.type_annotation) assert isinstance(type_anno, intermediate.ListTypeAnnotation) - assert isinstance(type_anno.items, intermediate.OurTypeAnnotation) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-11-10): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " f"Please contact the developers if you need this feature." ) - cls = type_anno.items.our_type - - interface_name = cpp_naming.interface_name(cls.name) - - deserialize_function = _determine_deserialize_function_to_call(cls=cls) + if isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation): + primitive_type = intermediate.try_primitive_type(type_anno.items) + interface_name = _PRIMITIVE_TYPE_TO_NATIVE_TYPE[primitive_type] + deserialize_function = _PRIMITIVE_TYPE_TO_DESERIALIZE[primitive_type] + else: + cls = type_anno.items.our_type + interface_name = f"types::{cpp_naming.interface_name(cls.name)}" + deserialize_function = _determine_deserialize_function_to_call(cls=cls) var_name = cpp_naming.variable_name(Identifier(f"the_{prop.name}")) json_prop_name = naming.json_property(prop.name) @@ -1211,7 +1230,7 @@ def _generate_deserialize_list_property( {var_name} = common::make_optional< {I}std::vector< -{II}std::shared_ptr +{II}std::shared_ptr<{interface_name}> {I}> >(); @@ -1224,7 +1243,7 @@ def _generate_deserialize_list_property( {I}: {var_json} ) {{ {I}common::optional< -{II}std::shared_ptr +{II}std::shared_ptr<{interface_name}> {I}> deserialized; {I}std::tie( @@ -1300,11 +1319,13 @@ def _generate_deserialize_property( else: assert_never(type_anno.our_type) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-11-10): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " @@ -2192,11 +2213,13 @@ def _generate_serialize_property(prop: intermediate.Property) -> Stripped: else: assert_never(type_anno.our_type) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-11-21): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " diff --git a/aas_core_codegen/cpp/verification/_generate.py b/aas_core_codegen/cpp/verification/_generate.py index 74a3bc842..07391810d 100644 --- a/aas_core_codegen/cpp/verification/_generate.py +++ b/aas_core_codegen/cpp/verification/_generate.py @@ -842,11 +842,13 @@ def _collect_constrained_primitive_properties( assert_never(type_anno.our_type) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-03-29): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " diff --git a/aas_core_codegen/cpp/visitation/_generate.py b/aas_core_codegen/cpp/visitation/_generate.py index 40c444655..727a0d345 100644 --- a/aas_core_codegen/cpp/visitation/_generate.py +++ b/aas_core_codegen/cpp/visitation/_generate.py @@ -341,11 +341,13 @@ def _generate_recursive_visit_for_property( else: assert_never(type_anno.our_type) elif isinstance(type_anno, intermediate.ListTypeAnnotation): - assert isinstance( - type_anno.items, intermediate.OurTypeAnnotation - ) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-03-29): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " diff --git a/aas_core_codegen/cpp/xmlization/_generate.py b/aas_core_codegen/cpp/xmlization/_generate.py index afec7a5b3..09adf6160 100644 --- a/aas_core_codegen/cpp/xmlization/_generate.py +++ b/aas_core_codegen/cpp/xmlization/_generate.py @@ -3022,23 +3022,30 @@ def _generate_deserialize_list_property( type_anno = intermediate.beneath_optional(prop.type_annotation) assert isinstance(type_anno, intermediate.ListTypeAnnotation) - assert isinstance(type_anno.items, intermediate.OurTypeAnnotation) and isinstance( - type_anno.items.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation) + or isinstance(type_anno.items, intermediate.OurTypeAnnotation) + and isinstance( + type_anno.items.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-12-10): We expect only lists of classes " f"at the moment, but you specified {type_anno}. " f"Please contact the developers if you need this feature." ) - item_type = cpp_common.generate_type( - type_annotation=type_anno.items, types_namespace=cpp_common.TYPES_NAMESPACE - ) - - from_element_name = cpp_naming.function_name( - Identifier(f"{type_anno.items.our_type.name}_from_element") - ) - + if isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation): + primitive_type = intermediate.try_primitive_type(type_anno.items) + item_type = _PRIMITIVE_TYPE_TO_NATIVE_TYPE[primitive_type] + from_element_name = _PRIMITIVE_TYPE_TO_DESERIALIZE[primitive_type] + else: + item_type = cpp_common.generate_type( + type_annotation=type_anno.items, types_namespace=cpp_common.TYPES_NAMESPACE + ) + from_element_name = cpp_naming.function_name( + Identifier(f"{type_anno.items.our_type.name}_from_element") + ) var_name = cpp_naming.variable_name(Identifier(f"the_{prop.name}")) # NOTE (mristin, 2023-12-12): @@ -4418,6 +4425,18 @@ class SelfClosingWriter {{ for primitive_type in intermediate.PrimitiveType ) +_PRIMITIVE_TYPE_TO_NATIVE_TYPE = { + intermediate.PrimitiveType.BOOL: "bool", + intermediate.PrimitiveType.INT: "int64_t", + intermediate.PrimitiveType.FLOAT: "double", + intermediate.PrimitiveType.STR: "std::wstring", + intermediate.PrimitiveType.BYTEARRAY: "std::vector", +} +assert all( + primitive_type in _PRIMITIVE_TYPE_TO_NATIVE_TYPE + for primitive_type in intermediate.PrimitiveType +) + def _generate_serialize_primitive_value( primitive_type: intermediate.PrimitiveType, var_name: Identifier @@ -4462,26 +4481,32 @@ def _generate_serialize_list( item_type_annotation: intermediate.TypeAnnotationUnion, var_name: Identifier ) -> Stripped: """Serialize the list at ``var_name``.""" - assert isinstance( - item_type_annotation, intermediate.OurTypeAnnotation - ) and isinstance( - item_type_annotation.our_type, - (intermediate.AbstractClass, intermediate.ConcreteClass), + assert ( + isinstance(item_type_annotation, intermediate.PrimitiveTypeAnnotation) + or isinstance(item_type_annotation, intermediate.OurTypeAnnotation) + and isinstance( + item_type_annotation.our_type, + (intermediate.AbstractClass, intermediate.ConcreteClass), + ) ), ( f"NOTE (mristin, 2023-12-20): We expect only lists of classes " f"at the moment, but you specified a list of {item_type_annotation}. " f"Please contact the developers if you need this feature." ) - item_cls = item_type_annotation.our_type - - item_serialize_function = cpp_naming.function_name( - Identifier(f"serialize_{item_cls.name}_as_element") - ) - - item_type = cpp_common.generate_type_with_const_ref_if_applicable( - type_annotation=item_type_annotation, types_namespace=cpp_common.TYPES_NAMESPACE - ) + if isinstance(item_type_annotation, intermediate.PrimitiveTypeAnnotation): + primitive_type = intermediate.try_primitive_type(item_type_annotation) + item_type = _PRIMITIVE_TYPE_TO_NATIVE_TYPE[primitive_type] + item_serialize_function = _PRIMITIVE_TYPE_TO_DESERIALIZE[primitive_type] + else: + item_cls = item_type_annotation.our_type + item_serialize_function = cpp_naming.function_name( + Identifier(f"serialize_{item_cls.name}_as_element") + ) + item_type = cpp_common.generate_type_with_const_ref_if_applicable( + type_annotation=item_type_annotation, + types_namespace=cpp_common.TYPES_NAMESPACE, + ) return Stripped( f"""\ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/common.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/common.cpp new file mode 100644 index 000000000..7689d23b2 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/common.cpp @@ -0,0 +1,14069 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" + +#pragma warning(push, 0) +#include +#pragma warning(pop) + +// NOTE (mristin): +// We use MultiByteToWideChar and WideCharToMulitByte from on Windows +// as std::codecvt is not robust enough on Windows, and produces invalid UTF-16 +// sequences as std::wstring. See: +// https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t, +// especially the comment: +// https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t#comment110447503_18597384 +#ifdef _WIN32 +#pragma warning(push, 0) +#include +#include +#include +#pragma warning(pop) +#else +// NOTE (mristin): +// We use codecvt although it has been deprecated. There has been not +// suitable replacement proposed yet, so we simply stick to it +// until there is. See: +// https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) +#endif + +namespace aas_core { +namespace aas_3_0 { +namespace common { + +std::string Concat( + const std::string& part0, + const std::string& part1 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60, + const std::string& part61 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + size += part61.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + result.append(part61); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60, + const std::string& part61, + const std::string& part62 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + size += part61.size(); + size += part62.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + result.append(part61); + result.append(part62); + + return result; +} + +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60, + const std::string& part61, + const std::string& part62, + const std::string& part63 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + size += part61.size(); + size += part62.size(); + size += part63.size(); + + std::string result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + result.append(part61); + result.append(part62); + result.append(part63); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60, + const std::wstring& part61 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + size += part61.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + result.append(part61); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60, + const std::wstring& part61, + const std::wstring& part62 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + size += part61.size(); + size += part62.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + result.append(part61); + result.append(part62); + + return result; +} + +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60, + const std::wstring& part61, + const std::wstring& part62, + const std::wstring& part63 +) { + size_t size = 0; + size += part0.size(); + size += part1.size(); + size += part2.size(); + size += part3.size(); + size += part4.size(); + size += part5.size(); + size += part6.size(); + size += part7.size(); + size += part8.size(); + size += part9.size(); + size += part10.size(); + size += part11.size(); + size += part12.size(); + size += part13.size(); + size += part14.size(); + size += part15.size(); + size += part16.size(); + size += part17.size(); + size += part18.size(); + size += part19.size(); + size += part20.size(); + size += part21.size(); + size += part22.size(); + size += part23.size(); + size += part24.size(); + size += part25.size(); + size += part26.size(); + size += part27.size(); + size += part28.size(); + size += part29.size(); + size += part30.size(); + size += part31.size(); + size += part32.size(); + size += part33.size(); + size += part34.size(); + size += part35.size(); + size += part36.size(); + size += part37.size(); + size += part38.size(); + size += part39.size(); + size += part40.size(); + size += part41.size(); + size += part42.size(); + size += part43.size(); + size += part44.size(); + size += part45.size(); + size += part46.size(); + size += part47.size(); + size += part48.size(); + size += part49.size(); + size += part50.size(); + size += part51.size(); + size += part52.size(); + size += part53.size(); + size += part54.size(); + size += part55.size(); + size += part56.size(); + size += part57.size(); + size += part58.size(); + size += part59.size(); + size += part60.size(); + size += part61.size(); + size += part62.size(); + size += part63.size(); + + std::wstring result; + result.reserve(size); + + result.append(part0); + result.append(part1); + result.append(part2); + result.append(part3); + result.append(part4); + result.append(part5); + result.append(part6); + result.append(part7); + result.append(part8); + result.append(part9); + result.append(part10); + result.append(part11); + result.append(part12); + result.append(part13); + result.append(part14); + result.append(part15); + result.append(part16); + result.append(part17); + result.append(part18); + result.append(part19); + result.append(part20); + result.append(part21); + result.append(part22); + result.append(part23); + result.append(part24); + result.append(part25); + result.append(part26); + result.append(part27); + result.append(part28); + result.append(part29); + result.append(part30); + result.append(part31); + result.append(part32); + result.append(part33); + result.append(part34); + result.append(part35); + result.append(part36); + result.append(part37); + result.append(part38); + result.append(part39); + result.append(part40); + result.append(part41); + result.append(part42); + result.append(part43); + result.append(part44); + result.append(part45); + result.append(part46); + result.append(part47); + result.append(part48); + result.append(part49); + result.append(part50); + result.append(part51); + result.append(part52); + result.append(part53); + result.append(part54); + result.append(part55); + result.append(part56); + result.append(part57); + result.append(part58); + result.append(part59); + result.append(part60); + result.append(part61); + result.append(part62); + result.append(part63); + + return result; +} + +std::string WstringToUtf8(const std::wstring& text) { + #ifdef _WIN32 + // Inspired by: + // https://stackoverflow.com/a/69410299/1600678 + + if (text.empty()) { + return ""; + } + + // NOTE (mristin): + // We put `max` into parentheses to avoid conflicts with + // `max` macro, see: + // https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std + + const size_t text_size = text.size(); + if ( + text_size + > static_cast( + (std::numeric_limits::max)() + ) + ) { + throw std::out_of_range( + common::Concat( + "The size of the text to be converted to UTF-8, ", + std::to_string(text_size), + ", exceeds the maximum int value ", + std::to_string((std::numeric_limits::max)()) + ) + ); + } + const int text_size_int = static_cast(text_size); + + const auto size_needed = WideCharToMultiByte( + CP_UTF8, + 0, + &(text[0]), + text_size_int, + nullptr, + 0, + nullptr, + nullptr + ); + + if (size_needed <= 0) { + throw std::runtime_error( + "WideCharToMultiByte() failed: " + std::to_string(size_needed) + ); + } + + std::string result(size_needed, 0); + + WideCharToMultiByte( + CP_UTF8, + 0, + &(text[0]), + text_size_int, + &(result[0]), + size_needed, + nullptr, + nullptr + ); + + return result; + #else + // NOTE (mristin): + // We use codecvt although it has been deprecated. There has been not + // suitable replacement proposed yet, so we simply stick to it + // until there is. See: + // https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement + + std::wstring_convert > conv; + return conv.to_bytes(text.data()); + #endif +} + +std::wstring Utf8ToWstring( + const char* utf8_text, + size_t utf8_text_size +) { + if (utf8_text_size == 0) { + return std::wstring(); + } + + #ifdef _WIN32 + // NOTE (mristin): + // We have to use MultiByteToWideChar from on Windows + // as std::codecvt is not robust enough on Windows and produces invalid UTF-16 + // sequences as std::wstring. See: + // https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t, + // especially the comment: + // https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t#comment110447503_18597384 + + // Inspired by: + // https://stackoverflow.com/a/69410299/1600678 + + if (utf8_text_size == std::string::npos) { + utf8_text_size = strlen(utf8_text); + } + + // NOTE (mristin): + // We put `max` into parentheses to avoid conflicts with + // `max` macro, see: + // https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std + + if ( + utf8_text_size + > static_cast( + (std::numeric_limits::max)() + ) + ) { + throw std::out_of_range( + common::Concat( + "The size of the UTF-8 text to be converted to wide string, ", + std::to_string(utf8_text_size), + ", exceeds the maximum int value ", + std::to_string((std::numeric_limits::max)()) + ) + ); + } + const int utf8_text_size_int = static_cast(utf8_text_size); + + const auto size_needed = MultiByteToWideChar( + CP_UTF8, + 0, + utf8_text, + utf8_text_size_int, + nullptr, + 0 + ); + if (size_needed <= 0) { + throw std::runtime_error( + "MultiByteToWideChar() failed: " + std::to_string(size_needed) + ); + } + + std::wstring result(size_needed, 0); + + MultiByteToWideChar( + CP_UTF8, + 0, + utf8_text, + utf8_text_size_int, + &(result[0]), + size_needed + ); + + return result; + + #else + // NOTE (mristin): + // We use codecvt although it has been deprecated. There has been not + // suitable replacement proposed yet, so we simply stick to it + // until there is. See: + // https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement + + std::wstring_convert,wchar_t> conv; + return conv.from_bytes(utf8_text); + #endif +} + +std::wstring Utf8ToWstring(const std::string& utf8_text) { + return Utf8ToWstring(&(utf8_text[0]), utf8_text.size()); +} + +} // namespace common +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/common.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/common.hpp new file mode 100644 index 000000000..1fa0aba2a --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/common.hpp @@ -0,0 +1,10092 @@ +#ifndef AAS_CORE_AAS_3_0_GUARD_ +#define AAS_CORE_AAS_3_0_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#pragma warning(push, 0) +#include +#include +#include +#include +#include +#include +#pragma warning(pop) + +// See: https://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +// Standard library provides std::optional in C++17 and above. +#pragma warning(push, 0) +#include +#pragma warning(pop) +#else +// We rely on https://github.com/TartanLlama/optional for optional structure. +#pragma warning(push, 0) +#include +#pragma warning(pop) +#endif + +// NOTE (mristin): +// We check for the version above C++20 as there is no C++23 literal yet, and +// std::expected is available only in C++23. +// See: https://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler +// and: http://eel.is/c++draft/cpp.predefined#1.1 +#if ((defined(_MSVC_LANG) && _MSVC_LANG > 202002L) || __cplusplus > 202002L) +// Standard library provides std::expected in C++23 and above. +#pragma warning(push, 0) +#include +#pragma warning(pop) +#else +// We rely on https://github.com/TartanLlama/expected for expected structure. +#pragma warning(push, 0) +#include +#pragma warning(pop) +#endif + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup common Common functionality used throughout the library + * @{ + */ +namespace common { + +// Please keep in sync with the preprocessing directives above in the include block. +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +// Standard library provides std::optional in C++17 and above. +using std::optional; +using std::nullopt; +using std::make_optional; +#else +using tl::optional; +using tl::nullopt; +using tl::make_optional; +#endif + +// Please keep in sync with the preprocessing directives above in the include block. +#if ((defined(_MSVC_LANG) && _MSVC_LANG > 202002L) || __cplusplus > 202002L) +using std::expected; +using std::unexpected; +using std::make_unexpected; +#else +using tl::expected; +using tl::unexpected; +using tl::make_unexpected; +#endif + +// Please keep in sync with the preprocessing directives above in the include block. +// Standard library provides std::make_unique in C++14 and above. +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) || __cplusplus >= 201402L) +using std::make_unique; +#else +// Inspired by: +// https://stackoverflow.com/questions/12547983/is-there-a-way-to-write-make-unique-in-vs2012 +template +std::unique_ptr make_unique() { + return std::unique_ptr( + new T() + ); +} + +template< + typename T, + typename A1 +> +std::unique_ptr make_unique( + A1&& a1 +) { + return std::unique_ptr( + new T( + std::forward(a1) + ) + ); +} + +template< + typename T, + typename A1, + typename A2 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9, + typename A10 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9, + A10&& a10 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9), + std::forward(a10) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9, + typename A10, + typename A11 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9, + A10&& a10, + A11&& a11 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9), + std::forward(a10), + std::forward(a11) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9, + typename A10, + typename A11, + typename A12 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9, + A10&& a10, + A11&& a11, + A12&& a12 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9), + std::forward(a10), + std::forward(a11), + std::forward(a12) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9, + typename A10, + typename A11, + typename A12, + typename A13 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9, + A10&& a10, + A11&& a11, + A12&& a12, + A13&& a13 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9), + std::forward(a10), + std::forward(a11), + std::forward(a12), + std::forward(a13) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9, + typename A10, + typename A11, + typename A12, + typename A13, + typename A14 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9, + A10&& a10, + A11&& a11, + A12&& a12, + A13&& a13, + A14&& a14 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9), + std::forward(a10), + std::forward(a11), + std::forward(a12), + std::forward(a13), + std::forward(a14) + ) + ); +} + +template< + typename T, + typename A1, + typename A2, + typename A3, + typename A4, + typename A5, + typename A6, + typename A7, + typename A8, + typename A9, + typename A10, + typename A11, + typename A12, + typename A13, + typename A14, + typename A15 +> +std::unique_ptr make_unique( + A1&& a1, + A2&& a2, + A3&& a3, + A4&& a4, + A5&& a5, + A6&& a6, + A7&& a7, + A8&& a8, + A9&& a9, + A10&& a10, + A11&& a11, + A12&& a12, + A13&& a13, + A14&& a14, + A15&& a15 +) { + return std::unique_ptr( + new T( + std::forward(a1), + std::forward(a2), + std::forward(a3), + std::forward(a4), + std::forward(a5), + std::forward(a6), + std::forward(a7), + std::forward(a8), + std::forward(a9), + std::forward(a10), + std::forward(a11), + std::forward(a12), + std::forward(a13), + std::forward(a14), + std::forward(a15) + ) + ); +} +#endif + +/** + * Concatenate 2 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \return a concatenation of the 2 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1 +); + +/** + * Concatenate 3 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \return a concatenation of the 3 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2 +); + +/** + * Concatenate 4 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \return a concatenation of the 4 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3 +); + +/** + * Concatenate 5 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \return a concatenation of the 5 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4 +); + +/** + * Concatenate 6 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \return a concatenation of the 6 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5 +); + +/** + * Concatenate 7 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \return a concatenation of the 7 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6 +); + +/** + * Concatenate 8 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \return a concatenation of the 8 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7 +); + +/** + * Concatenate 9 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \return a concatenation of the 9 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8 +); + +/** + * Concatenate 10 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \return a concatenation of the 10 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9 +); + +/** + * Concatenate 11 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \return a concatenation of the 11 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10 +); + +/** + * Concatenate 12 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \return a concatenation of the 12 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11 +); + +/** + * Concatenate 13 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \return a concatenation of the 13 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12 +); + +/** + * Concatenate 14 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \return a concatenation of the 14 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13 +); + +/** + * Concatenate 15 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \return a concatenation of the 15 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14 +); + +/** + * Concatenate 16 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \return a concatenation of the 16 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15 +); + +/** + * Concatenate 17 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \return a concatenation of the 17 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16 +); + +/** + * Concatenate 18 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \return a concatenation of the 18 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17 +); + +/** + * Concatenate 19 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \return a concatenation of the 19 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18 +); + +/** + * Concatenate 20 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \return a concatenation of the 20 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19 +); + +/** + * Concatenate 21 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \return a concatenation of the 21 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20 +); + +/** + * Concatenate 22 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \return a concatenation of the 22 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21 +); + +/** + * Concatenate 23 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \return a concatenation of the 23 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22 +); + +/** + * Concatenate 24 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \return a concatenation of the 24 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23 +); + +/** + * Concatenate 25 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \return a concatenation of the 25 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24 +); + +/** + * Concatenate 26 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \return a concatenation of the 26 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25 +); + +/** + * Concatenate 27 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \return a concatenation of the 27 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26 +); + +/** + * Concatenate 28 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \return a concatenation of the 28 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27 +); + +/** + * Concatenate 29 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \return a concatenation of the 29 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28 +); + +/** + * Concatenate 30 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \return a concatenation of the 30 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29 +); + +/** + * Concatenate 31 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \return a concatenation of the 31 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30 +); + +/** + * Concatenate 32 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \return a concatenation of the 32 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31 +); + +/** + * Concatenate 33 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \return a concatenation of the 33 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32 +); + +/** + * Concatenate 34 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \return a concatenation of the 34 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33 +); + +/** + * Concatenate 35 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \return a concatenation of the 35 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34 +); + +/** + * Concatenate 36 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \return a concatenation of the 36 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35 +); + +/** + * Concatenate 37 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \return a concatenation of the 37 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36 +); + +/** + * Concatenate 38 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \return a concatenation of the 38 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37 +); + +/** + * Concatenate 39 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \return a concatenation of the 39 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38 +); + +/** + * Concatenate 40 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \return a concatenation of the 40 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39 +); + +/** + * Concatenate 41 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \return a concatenation of the 41 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40 +); + +/** + * Concatenate 42 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \return a concatenation of the 42 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41 +); + +/** + * Concatenate 43 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \return a concatenation of the 43 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42 +); + +/** + * Concatenate 44 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \return a concatenation of the 44 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43 +); + +/** + * Concatenate 45 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \return a concatenation of the 45 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44 +); + +/** + * Concatenate 46 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \return a concatenation of the 46 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45 +); + +/** + * Concatenate 47 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \return a concatenation of the 47 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46 +); + +/** + * Concatenate 48 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \return a concatenation of the 48 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47 +); + +/** + * Concatenate 49 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \return a concatenation of the 49 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48 +); + +/** + * Concatenate 50 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \return a concatenation of the 50 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49 +); + +/** + * Concatenate 51 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \return a concatenation of the 51 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50 +); + +/** + * Concatenate 52 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \return a concatenation of the 52 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51 +); + +/** + * Concatenate 53 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \return a concatenation of the 53 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52 +); + +/** + * Concatenate 54 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \return a concatenation of the 54 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53 +); + +/** + * Concatenate 55 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \return a concatenation of the 55 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54 +); + +/** + * Concatenate 56 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \return a concatenation of the 56 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55 +); + +/** + * Concatenate 57 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \return a concatenation of the 57 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56 +); + +/** + * Concatenate 58 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \return a concatenation of the 58 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57 +); + +/** + * Concatenate 59 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \return a concatenation of the 59 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58 +); + +/** + * Concatenate 60 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \return a concatenation of the 60 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59 +); + +/** + * Concatenate 61 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \return a concatenation of the 61 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60 +); + +/** + * Concatenate 62 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \param part61 62nd part of the concatenation + * \return a concatenation of the 62 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60, + const std::string& part61 +); + +/** + * Concatenate 63 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \param part61 62nd part of the concatenation + * \param part62 63rd part of the concatenation + * \return a concatenation of the 63 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60, + const std::string& part61, + const std::string& part62 +); + +/** + * Concatenate 64 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \param part61 62nd part of the concatenation + * \param part62 63rd part of the concatenation + * \param part63 64th part of the concatenation + * \return a concatenation of the 64 parts + */ +std::string Concat( + const std::string& part0, + const std::string& part1, + const std::string& part2, + const std::string& part3, + const std::string& part4, + const std::string& part5, + const std::string& part6, + const std::string& part7, + const std::string& part8, + const std::string& part9, + const std::string& part10, + const std::string& part11, + const std::string& part12, + const std::string& part13, + const std::string& part14, + const std::string& part15, + const std::string& part16, + const std::string& part17, + const std::string& part18, + const std::string& part19, + const std::string& part20, + const std::string& part21, + const std::string& part22, + const std::string& part23, + const std::string& part24, + const std::string& part25, + const std::string& part26, + const std::string& part27, + const std::string& part28, + const std::string& part29, + const std::string& part30, + const std::string& part31, + const std::string& part32, + const std::string& part33, + const std::string& part34, + const std::string& part35, + const std::string& part36, + const std::string& part37, + const std::string& part38, + const std::string& part39, + const std::string& part40, + const std::string& part41, + const std::string& part42, + const std::string& part43, + const std::string& part44, + const std::string& part45, + const std::string& part46, + const std::string& part47, + const std::string& part48, + const std::string& part49, + const std::string& part50, + const std::string& part51, + const std::string& part52, + const std::string& part53, + const std::string& part54, + const std::string& part55, + const std::string& part56, + const std::string& part57, + const std::string& part58, + const std::string& part59, + const std::string& part60, + const std::string& part61, + const std::string& part62, + const std::string& part63 +); + +/** + * Concatenate 2 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \return a concatenation of the 2 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1 +); + +/** + * Concatenate 3 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \return a concatenation of the 3 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2 +); + +/** + * Concatenate 4 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \return a concatenation of the 4 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3 +); + +/** + * Concatenate 5 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \return a concatenation of the 5 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4 +); + +/** + * Concatenate 6 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \return a concatenation of the 6 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5 +); + +/** + * Concatenate 7 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \return a concatenation of the 7 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6 +); + +/** + * Concatenate 8 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \return a concatenation of the 8 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7 +); + +/** + * Concatenate 9 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \return a concatenation of the 9 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8 +); + +/** + * Concatenate 10 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \return a concatenation of the 10 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9 +); + +/** + * Concatenate 11 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \return a concatenation of the 11 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10 +); + +/** + * Concatenate 12 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \return a concatenation of the 12 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11 +); + +/** + * Concatenate 13 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \return a concatenation of the 13 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12 +); + +/** + * Concatenate 14 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \return a concatenation of the 14 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13 +); + +/** + * Concatenate 15 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \return a concatenation of the 15 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14 +); + +/** + * Concatenate 16 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \return a concatenation of the 16 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15 +); + +/** + * Concatenate 17 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \return a concatenation of the 17 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16 +); + +/** + * Concatenate 18 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \return a concatenation of the 18 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17 +); + +/** + * Concatenate 19 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \return a concatenation of the 19 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18 +); + +/** + * Concatenate 20 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \return a concatenation of the 20 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19 +); + +/** + * Concatenate 21 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \return a concatenation of the 21 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20 +); + +/** + * Concatenate 22 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \return a concatenation of the 22 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21 +); + +/** + * Concatenate 23 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \return a concatenation of the 23 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22 +); + +/** + * Concatenate 24 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \return a concatenation of the 24 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23 +); + +/** + * Concatenate 25 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \return a concatenation of the 25 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24 +); + +/** + * Concatenate 26 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \return a concatenation of the 26 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25 +); + +/** + * Concatenate 27 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \return a concatenation of the 27 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26 +); + +/** + * Concatenate 28 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \return a concatenation of the 28 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27 +); + +/** + * Concatenate 29 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \return a concatenation of the 29 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28 +); + +/** + * Concatenate 30 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \return a concatenation of the 30 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29 +); + +/** + * Concatenate 31 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \return a concatenation of the 31 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30 +); + +/** + * Concatenate 32 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \return a concatenation of the 32 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31 +); + +/** + * Concatenate 33 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \return a concatenation of the 33 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32 +); + +/** + * Concatenate 34 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \return a concatenation of the 34 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33 +); + +/** + * Concatenate 35 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \return a concatenation of the 35 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34 +); + +/** + * Concatenate 36 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \return a concatenation of the 36 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35 +); + +/** + * Concatenate 37 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \return a concatenation of the 37 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36 +); + +/** + * Concatenate 38 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \return a concatenation of the 38 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37 +); + +/** + * Concatenate 39 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \return a concatenation of the 39 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38 +); + +/** + * Concatenate 40 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \return a concatenation of the 40 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39 +); + +/** + * Concatenate 41 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \return a concatenation of the 41 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40 +); + +/** + * Concatenate 42 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \return a concatenation of the 42 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41 +); + +/** + * Concatenate 43 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \return a concatenation of the 43 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42 +); + +/** + * Concatenate 44 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \return a concatenation of the 44 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43 +); + +/** + * Concatenate 45 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \return a concatenation of the 45 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44 +); + +/** + * Concatenate 46 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \return a concatenation of the 46 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45 +); + +/** + * Concatenate 47 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \return a concatenation of the 47 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46 +); + +/** + * Concatenate 48 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \return a concatenation of the 48 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47 +); + +/** + * Concatenate 49 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \return a concatenation of the 49 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48 +); + +/** + * Concatenate 50 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \return a concatenation of the 50 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49 +); + +/** + * Concatenate 51 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \return a concatenation of the 51 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50 +); + +/** + * Concatenate 52 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \return a concatenation of the 52 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51 +); + +/** + * Concatenate 53 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \return a concatenation of the 53 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52 +); + +/** + * Concatenate 54 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \return a concatenation of the 54 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53 +); + +/** + * Concatenate 55 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \return a concatenation of the 55 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54 +); + +/** + * Concatenate 56 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \return a concatenation of the 56 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55 +); + +/** + * Concatenate 57 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \return a concatenation of the 57 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56 +); + +/** + * Concatenate 58 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \return a concatenation of the 58 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57 +); + +/** + * Concatenate 59 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \return a concatenation of the 59 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58 +); + +/** + * Concatenate 60 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \return a concatenation of the 60 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59 +); + +/** + * Concatenate 61 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \return a concatenation of the 61 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60 +); + +/** + * Concatenate 62 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \param part61 62nd part of the concatenation + * \return a concatenation of the 62 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60, + const std::wstring& part61 +); + +/** + * Concatenate 63 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \param part61 62nd part of the concatenation + * \param part62 63rd part of the concatenation + * \return a concatenation of the 63 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60, + const std::wstring& part61, + const std::wstring& part62 +); + +/** + * Concatenate 64 strings. + * + * \param part0 1st part of the concatenation + * \param part1 2nd part of the concatenation + * \param part2 3rd part of the concatenation + * \param part3 4th part of the concatenation + * \param part4 5th part of the concatenation + * \param part5 6th part of the concatenation + * \param part6 7th part of the concatenation + * \param part7 8th part of the concatenation + * \param part8 9th part of the concatenation + * \param part9 10th part of the concatenation + * \param part10 11st part of the concatenation + * \param part11 12nd part of the concatenation + * \param part12 13rd part of the concatenation + * \param part13 14th part of the concatenation + * \param part14 15th part of the concatenation + * \param part15 16th part of the concatenation + * \param part16 17th part of the concatenation + * \param part17 18th part of the concatenation + * \param part18 19th part of the concatenation + * \param part19 20th part of the concatenation + * \param part20 21st part of the concatenation + * \param part21 22nd part of the concatenation + * \param part22 23rd part of the concatenation + * \param part23 24th part of the concatenation + * \param part24 25th part of the concatenation + * \param part25 26th part of the concatenation + * \param part26 27th part of the concatenation + * \param part27 28th part of the concatenation + * \param part28 29th part of the concatenation + * \param part29 30th part of the concatenation + * \param part30 31st part of the concatenation + * \param part31 32nd part of the concatenation + * \param part32 33rd part of the concatenation + * \param part33 34th part of the concatenation + * \param part34 35th part of the concatenation + * \param part35 36th part of the concatenation + * \param part36 37th part of the concatenation + * \param part37 38th part of the concatenation + * \param part38 39th part of the concatenation + * \param part39 40th part of the concatenation + * \param part40 41st part of the concatenation + * \param part41 42nd part of the concatenation + * \param part42 43rd part of the concatenation + * \param part43 44th part of the concatenation + * \param part44 45th part of the concatenation + * \param part45 46th part of the concatenation + * \param part46 47th part of the concatenation + * \param part47 48th part of the concatenation + * \param part48 49th part of the concatenation + * \param part49 50th part of the concatenation + * \param part50 51st part of the concatenation + * \param part51 52nd part of the concatenation + * \param part52 53rd part of the concatenation + * \param part53 54th part of the concatenation + * \param part54 55th part of the concatenation + * \param part55 56th part of the concatenation + * \param part56 57th part of the concatenation + * \param part57 58th part of the concatenation + * \param part58 59th part of the concatenation + * \param part59 60th part of the concatenation + * \param part60 61st part of the concatenation + * \param part61 62nd part of the concatenation + * \param part62 63rd part of the concatenation + * \param part63 64th part of the concatenation + * \return a concatenation of the 64 parts + */ +std::wstring Concat( + const std::wstring& part0, + const std::wstring& part1, + const std::wstring& part2, + const std::wstring& part3, + const std::wstring& part4, + const std::wstring& part5, + const std::wstring& part6, + const std::wstring& part7, + const std::wstring& part8, + const std::wstring& part9, + const std::wstring& part10, + const std::wstring& part11, + const std::wstring& part12, + const std::wstring& part13, + const std::wstring& part14, + const std::wstring& part15, + const std::wstring& part16, + const std::wstring& part17, + const std::wstring& part18, + const std::wstring& part19, + const std::wstring& part20, + const std::wstring& part21, + const std::wstring& part22, + const std::wstring& part23, + const std::wstring& part24, + const std::wstring& part25, + const std::wstring& part26, + const std::wstring& part27, + const std::wstring& part28, + const std::wstring& part29, + const std::wstring& part30, + const std::wstring& part31, + const std::wstring& part32, + const std::wstring& part33, + const std::wstring& part34, + const std::wstring& part35, + const std::wstring& part36, + const std::wstring& part37, + const std::wstring& part38, + const std::wstring& part39, + const std::wstring& part40, + const std::wstring& part41, + const std::wstring& part42, + const std::wstring& part43, + const std::wstring& part44, + const std::wstring& part45, + const std::wstring& part46, + const std::wstring& part47, + const std::wstring& part48, + const std::wstring& part49, + const std::wstring& part50, + const std::wstring& part51, + const std::wstring& part52, + const std::wstring& part53, + const std::wstring& part54, + const std::wstring& part55, + const std::wstring& part56, + const std::wstring& part57, + const std::wstring& part58, + const std::wstring& part59, + const std::wstring& part60, + const std::wstring& part61, + const std::wstring& part62, + const std::wstring& part63 +); + +/** + * Check if all the elements satisfy the \p condition. + * + * \param condition returning a boolean to be checked for each element + * \param container to be iterated through + * \return `true` if all the elements of \p container satisfy the \p condition + */ +template +bool All( + FunctorT condition, + const ContainerT& container +) { + for (const auto& item : container ) { + if (!condition(item)) { + return false; + } + } + return true; +} + +/** + * Check if any of the elements satisfy the \p condition. + * + * \param condition returning a boolean to be checked for each element + * \param container to be iterated through + * \return `true` if any of the elements of \p container satisfy the \p condition + */ +template +bool Some( + FunctorT condition, + const ContainerT& container +) { + for (const auto& item : container ) { + if (condition(item)) { + return true; + } + } + return false; +} + +/** + * Check if all the numbers in the range `[start, end)` satisfy the \p condition. + * + * \param condition returning a boolean to be checked for each number + * \param start of the range + * \param end of the range + * \return \parblock + * `true` if all the numbers between \p start and \p end (excluded) + * satisfy the \p condition + * \endparblock + */ +template +bool AllRange( + FunctorT condition, + size_t start, + size_t end +) { + for (size_t i = start; i < end; ++i) { + if (!condition(i)) { + return false; + } + } + return true; +} + +/** + * Check if any number in the range `[start, end)` satisfy the \p condition. + * + * \param condition returning a boolean to be checked for each number + * \param start of the range + * \param end of the range + * \return \parblock + * `true` if any number between \p start and + * \p end (excluded) satisfy the \p condition + * \endparblock + */ +template +bool SomeRange( + FunctorT condition, + size_t start, + size_t end +) { + for (size_t i = start; i < end; ++i) { + if (condition(i)) { + return true; + } + } + return false; +} + +/** + * Check if the \p container contains the \p value. + * + * \param container to be searched through + * \param value to be search for + * \return `true` if \p value is in the \p container + */ +template +bool Contains( + const ContainerT& container, + const ValueT& value +) { + const auto container_begin = std::begin(container); + const auto container_end = std::end(container); + return std::find( + container_begin, + container_end, + value + ) != container_end; +} + +/** + * Convert platform-independent the wide string to a UTF-8 string. + * + * \param text to be converted + * \return UTF-8 encoded \p text + */ +std::string WstringToUtf8(const std::wstring& text); + +/** + * Convert platform-independent the UTF-8 encoded string to a wide string. + * + * \param utf8_text UTF-8 encoded text to be converted + * \param utf8_text_size size of the text to be converted. If std::string::npos, + * the \p utf8_text is assumed to be null-terminated and the size is determined + * using `strlen`. + * \return the wide-string representation + */ +std::wstring Utf8ToWstring( + const char* utf8_text, + size_t utf8_text_size = std::string::npos +); + +/** + * Convert platform-independent the UTF-8 encoded string to a wide string. + * + * \param utf8_text UTF-8 encoded text to be converted + * \return wide string + */ +std::wstring Utf8ToWstring(const std::string& utf8_text); + +} // namespace common +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/constants.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/constants.cpp new file mode 100644 index 000000000..dd5eaef37 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/constants.cpp @@ -0,0 +1,27 @@ +#include "aas_core/aas_3_0/constants.hpp" + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +namespace aas_core { +namespace aas_3_0 { +namespace constants { + +std::size_t HashBytes::operator()( + const std::vector& bytes +) const { + std::size_t result = 0; + const std::size_t prime = 31; + const std::size_t size = bytes.size(); + for (std::size_t i = 0; i < size; ++i) { + result = bytes[i] + (result * prime); + } + return result; +} + +} // namespace constants +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/constants.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/constants.hpp new file mode 100644 index 000000000..76d34deff --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/constants.hpp @@ -0,0 +1,40 @@ +#ifndef AAS_CORE_AAS_3_0_CONSTANTS_GUARD_ +#define AAS_CORE_AAS_3_0_CONSTANTS_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup constants Pre-defined constants of the meta-model + * @{ + */ +namespace constants { + +/** + * Hash a blob of bytes based on the Java's String hash. + */ +struct HashBytes { + std::size_t operator()(const std::vector& bytes) const; +}; + +} // namespace common +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_CONSTANTS_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/enhancing.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/enhancing.hpp new file mode 100644 index 000000000..36f1c1211 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/enhancing.hpp @@ -0,0 +1,638 @@ +#ifndef AAS_CORE_AAS_3_0_ENHANCING_GUARD_ +#define AAS_CORE_AAS_3_0_ENHANCING_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/stringification.hpp" +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup enhancing Enhance instances of the model with your custom enhancements. + * @{ + */ +namespace enhancing { + +// region Forward declarations + +template +std::shared_ptr< + types::IMyClass +> Wrap( + const std::shared_ptr< + types::IMyClass + >& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +); + +template +std::shared_ptr< + types::IListOfPrimitives +> Wrap( + const std::shared_ptr< + types::IListOfPrimitives + >& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +); + +// endregion Forward declarations + +/// \cond HIDDEN +namespace impl { + +template +class IEnhanced { + public: + virtual const std::shared_ptr& enhancement() const = 0; + + virtual std::shared_ptr& mutable_enhancement() = 0; + + virtual void set_enhancement( + std::shared_ptr value + ) = 0; + + virtual ~IEnhanced() = default; +}; + +template +class EnhancedMyClass + : virtual public types::IMyClass, + virtual public IEnhanced { + public: + types::ModelType model_type() const override { + return types::ModelType::kMyClass; + } + + const std::shared_ptr& enhancement() const { + return enhancement_; + } + + std::shared_ptr& mutable_enhancement() { + return enhancement_; + } + + void set_enhancement( + std::shared_ptr value + ) { + enhancement_ = std::move(value); + } + + EnhancedMyClass( + std::shared_ptr instance, + std::shared_ptr enhancement + ) : + instance_(instance), + enhancement_(enhancement) { + // Intentionally empty. + } + + virtual ~EnhancedMyClass() = default; + + private: + std::shared_ptr instance_; + std::shared_ptr enhancement_; +}; + +template +class EnhancedListOfPrimitives + : virtual public types::IListOfPrimitives, + virtual public IEnhanced { + public: + types::ModelType model_type() const override { + return types::ModelType::kListOfPrimitives; + } + + const std::vector& strings() const override { + return instance_->strings(); + } + + std::vector& mutable_strings() override { + return instance_->mutable_strings(); + } + + void set_strings( + std::vector value + ) override { + instance_->set_strings(value); + } + + const std::vector& integers() const override { + return instance_->integers(); + } + + std::vector& mutable_integers() override { + return instance_->mutable_integers(); + } + + void set_integers( + std::vector value + ) override { + instance_->set_integers(value); + } + + const std::vector& booleans() const override { + return instance_->booleans(); + } + + std::vector& mutable_booleans() override { + return instance_->mutable_booleans(); + } + + void set_booleans( + std::vector value + ) override { + instance_->set_booleans(value); + } + + const std::vector< + std::shared_ptr + >& classes() const override { + return instance_->classes(); + } + + std::vector< + std::shared_ptr + >& mutable_classes() override { + return instance_->mutable_classes(); + } + + void set_classes( + std::vector< + std::shared_ptr + > value + ) override { + instance_->set_classes(value); + } + + const std::shared_ptr& enhancement() const { + return enhancement_; + } + + std::shared_ptr& mutable_enhancement() { + return enhancement_; + } + + void set_enhancement( + std::shared_ptr value + ) { + enhancement_ = std::move(value); + } + + EnhancedListOfPrimitives( + std::shared_ptr instance, + std::shared_ptr enhancement + ) : + instance_(instance), + enhancement_(enhancement) { + // Intentionally empty. + } + + virtual ~EnhancedListOfPrimitives() = default; + + private: + std::shared_ptr instance_; + std::shared_ptr enhancement_; +}; + +/** + * Wrap \p that with an enhanced instance. + * + * \param that instance to be wrapped and enhanced + * \param factory to produce an enhancement based on an instance + * \return Enhanced instance, or `that` if no enhancement produced + * + * \tparam E type of the enhancement + */ +template +std::shared_ptr WrapMyClass( + const std::shared_ptr& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +) { + // We assume that we already checked whether `that` has been enhanced + // in the caller. + + // No properties to be recursively enhanced. + + std::shared_ptr enh( + factory(that) + ); + return (enh == nullptr) + ? that + : std::shared_ptr( + new EnhancedMyClass( + that, + enh + ) + ); +} + +/** + * Wrap \p that with an enhanced instance. + * + * \param that instance to be wrapped and enhanced + * \param factory to produce an enhancement based on an instance + * \return Enhanced instance, or `that` if no enhancement produced + * + * \tparam E type of the enhancement + */ +template +std::shared_ptr WrapListOfPrimitives( + const std::shared_ptr& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +) { + // We assume that we already checked whether `that` has been enhanced + // in the caller. + + { + const std::vector& value( + that->strings() + ); + const std::size_t size = value.size(); + + std::vector wrapped; + wrapped.reserve(size); + + for ( + const std::wstring& item + : value + ) { + wrapped.emplace_back( + Wrap( + item, + factory + ) + ); + } + + that->set_strings( + std::move(wrapped) + ); + } + + { + const std::vector& value( + that->integers() + ); + const std::size_t size = value.size(); + + std::vector wrapped; + wrapped.reserve(size); + + for ( + int64_t item + : value + ) { + wrapped.emplace_back( + Wrap( + item, + factory + ) + ); + } + + that->set_integers( + std::move(wrapped) + ); + } + + { + const std::vector& value( + that->booleans() + ); + const std::size_t size = value.size(); + + std::vector wrapped; + wrapped.reserve(size); + + for ( + bool item + : value + ) { + wrapped.emplace_back( + Wrap( + item, + factory + ) + ); + } + + that->set_booleans( + std::move(wrapped) + ); + } + + { + const std::vector< + std::shared_ptr + >& value( + that->classes() + ); + const std::size_t size = value.size(); + + std::vector< + std::shared_ptr + > wrapped; + wrapped.reserve(size); + + for ( + const std::shared_ptr& item + : value + ) { + wrapped.emplace_back( + Wrap( + item, + factory + ) + ); + } + + that->set_classes( + std::move(wrapped) + ); + } + + std::shared_ptr enh( + factory(that) + ); + return (enh == nullptr) + ? that + : std::shared_ptr( + new EnhancedListOfPrimitives( + that, + enh + ) + ); +} + +/** + * Assert that the \p that instance has not been already enhanced. + * + * \param that instance to be checked + * \tparam E type of the enhancement + * \tparam T interface type of \p that instance + * \throw std::logic_error if \p that already enhanced + */ +template< + typename E, + typename T, + typename std::enable_if< + std::is_base_of::value + >::type* = nullptr +> +void AssertNotEnhanced( + const std::shared_ptr& that +) { + std::shared_ptr > enhanced( + std::dynamic_pointer_cast< + impl::IEnhanced + >(that) + ); + if (enhanced != nullptr) { + throw std::logic_error( + common::Concat( + "An instance of ", + stringification::to_string(that->model_type()), + " has been already wrapped." + ) + ); + } +} + +} // namespace impl +/// \endcond + +/** + * Wrap \p that instance recursively with the enhancement produced by the \p factory. + * + * The factory decides itself whether it will produce an enhancement for + * \p that instance, or not. Even if no enhancement has been produced for \p that + * instance, we will still continue to enhance the instances referenced + * by \p that instance recursively. + * + * \param that instance to wrap + * \param factory to selectively produce an enhancement + * \return enhanced \p that instance + * \throw std::logic_error if \p that instance has been already wrapped. + * \tparam E type of the enhancement + */ +///@{ + +template +std::shared_ptr< + types::IClass +> Wrap( + const std::shared_ptr< + types::IClass + >& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +) { + impl::AssertNotEnhanced< + E, + types::IClass + >(that); + + switch (that->model_type()) { + case types::ModelType::kMyClass: + return impl::WrapMyClass( + std::dynamic_pointer_cast< + types::IMyClass + >(that), + factory + ); + break; + case types::ModelType::kListOfPrimitives: + return impl::WrapListOfPrimitives( + std::dynamic_pointer_cast< + types::IListOfPrimitives + >(that), + factory + ); + break; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast( + that->model_type() + ) + ) + ) + ); + break; + } +} + +template +std::shared_ptr< + types::IMyClass +> Wrap( + const std::shared_ptr< + types::IMyClass + >& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +) { + impl::AssertNotEnhanced< + E, + types::IMyClass + >(that); + + switch (that->model_type()) { + case types::ModelType::kMyClass: + return impl::WrapMyClass( + that, + factory + ); + break; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast( + that->model_type() + ) + ) + ) + ); + break; + } +} + +template +std::shared_ptr< + types::IListOfPrimitives +> Wrap( + const std::shared_ptr< + types::IListOfPrimitives + >& that, + const std::function< + std::shared_ptr( + const std::shared_ptr& + ) + >& factory +) { + impl::AssertNotEnhanced< + E, + types::IListOfPrimitives + >(that); + + switch (that->model_type()) { + case types::ModelType::kListOfPrimitives: + return impl::WrapListOfPrimitives( + that, + factory + ); + break; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast( + that->model_type() + ) + ) + ) + ); + break; + } +} + +///@}} + +/** + * Try to unwrap the enhancement from \p that instance. + * + * \param that instance possibly wrapped with an enhancement + * \return the enhancement, or `nullptr` if \p that instance has not been wrapped + * \tparam E type of the enhancement + */ +template +std::shared_ptr Unwrap( + const std::shared_ptr& that +) { + const std::shared_ptr >& maybe_enhanced( + std::dynamic_pointer_cast >(that) + ); + + if (!maybe_enhanced) { + return nullptr; + } + + return maybe_enhanced->enhancement(); +} + +/** + * Unwrap the enhancement from \p that instance. + * + * \remark \p that instance must have been wrapped before. + * + * \param that instance expected to be wrapped with an enhancement + * \return the enhancement + * \throw std::invalid_argument if \p that instance has not been wrapped + * \tparam E type of the enhancement + */ +template +std::shared_ptr MustUnwrap( + const std::shared_ptr& that +) { + std::shared_ptr enhancement( + Unwrap(that) + ); + if (!enhancement) { + throw std::invalid_argument( + common::Concat( + "Expected an instance of ", + stringification::to_string(that->model_type()), + " to have been already wrapped with an enhancement, " + "but it has been not." + ) + ); + } + return enhancement; +} + +} // namespace enhancing +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_ENHANCING_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/iteration.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/iteration.cpp new file mode 100644 index 000000000..be373c585 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/iteration.cpp @@ -0,0 +1,1229 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/iteration.hpp" + +namespace aas_core { +namespace aas_3_0 { +namespace iteration { + +// region Pathing + +/** + * Translate the enumeration literal \p property to text. + * + * \param property to be converted into text + * \return text representation of \p property + * \throw std::invalid_argument if \p property invalid + */ +std::wstring PropertyToWstring( + Property property +) { + switch (property) { + case Property::kBooleans: + return L"booleans"; + case Property::kClasses: + return L"classes"; + case Property::kIntegers: + return L"integers"; + case Property::kStrings: + return L"strings"; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected property literal: ", + std::to_string( + static_cast(property) + ) + ) + ); + } +} // function to_wstring + +// region struct PropertySegment + +PropertySegment::PropertySegment(Property a_property) { + property = a_property; +} + +std::wstring PropertySegment::ToWstring() const { + return common::Concat( + L".", + PropertyToWstring(property) + ); +} + +std::unique_ptr PropertySegment::Clone() const { + return common::make_unique(*this); +} + +// endregion struct PropertySegment + +// region struct IndexSegment + +IndexSegment::IndexSegment(size_t an_index) { + index = an_index; +} + +std::wstring IndexSegment::ToWstring() const { + return common::Concat( + L"[", + std::to_wstring(index), + L"]" + ); +} + +std::unique_ptr IndexSegment::Clone() const { + return common::make_unique(*this); +} + +// endregion struct IndexSegment + +// region struct Path + +Path::Path() { + // Intentionally empty. +} + +Path::Path(const Path& other) { + for (const std::unique_ptr& segment : other.segments) { + segments.emplace_back(segment->Clone()); + } +} + +Path::Path(Path&& other) { + segments = std::move(other.segments); +} + +Path& Path::operator=(const Path& other) { + segments.clear(); + for (const std::unique_ptr& segment : other.segments) { + segments.emplace_back(segment->Clone()); + } + return *this; +} + +Path& Path::operator=(Path&& other) { + if (this != &other) { + segments = std::move(other.segments); + } + return *this; +} + +std::wstring Path::ToWstring() const { + std::vector parts; + parts.reserve(segments.size()); + + for (const std::unique_ptr& segment : segments ) { + parts.emplace_back(segment->ToWstring()); + } + + size_t size = 0; + for (const std::wstring& part : parts) { + size += part.size(); + } + + std::wstring result; + result.reserve(size); + for (const std::wstring& part : parts) { + result.append(part); + } + + return result; +} + +// endregion struct Path + +// endregion Pathing + +// region Non-recursive iteration + +/** + * This iterator is always done as IMyClass + * references no other instances. + */ +class IteratorOverMyClass : public impl::IIterator { + public: + IteratorOverMyClass( + const std::shared_ptr& + ) { + // Intentionally empty. + } + + void Start() override { + // Intentionally empty. + } + + void Next() override { + throw std::logic_error( + "You want to move " + "an IteratorOverMyClass, " + "but the iterator is always done as " + "IMyClass " + "references no other instances." + ); + } + + bool Done() const override { + return true; + } + + const std::shared_ptr& Get() const override { + throw std::logic_error( + "You want to get from an IteratorOverMyClass, " + "but the iterator is always done as " + "IMyClass references " + "no other instances." + ); + } + + long Index() const override { + return -1; + } + + std::unique_ptr Clone() const override { + return common::make_unique(*this); + } + + void PrependToPath(Path*) const override { + throw std::logic_error( + "You want to prepend to path from an IteratorOverMyClass, " + "but the iterator is always done as " + "IMyClass references " + "no other instances." + ); + } + + ~IteratorOverMyClass() override = default; +}; // class IteratorOverMyClass + +// region Non-recursive iteration over IListOfPrimitives + +/** + * Iterate non-recursively over the instances referenced from an instance. + */ +class IteratorOverListOfPrimitives : public impl::IIterator { + public: + IteratorOverListOfPrimitives( + const std::shared_ptr& instance + ); + void Start() override; + void Next() override; + bool Done() const override; + const std::shared_ptr& Get() const override; + long Index() const override; + void PrependToPath(Path* path) const override; + std::unique_ptr Clone() const override; + ~IteratorOverListOfPrimitives() override = default; + + private: + // We make instance_ a pointer, so that we can follow the rule-of-zero. + const std::shared_ptr* instance_; + // We make casted_ a pointer, so that we can follow the rule-of-zero. + const types::IListOfPrimitives* casted_; + std::uint32_t state_; + common::optional property_; + common::optional cursor_; // in yield-from loops + std::shared_ptr item_; + long index_; // in total iteration + bool done_; + + void Execute(); +}; // class IteratorOverListOfPrimitives + +IteratorOverListOfPrimitives::IteratorOverListOfPrimitives( + const std::shared_ptr& instance +) : + instance_(&instance), + // NOTE (mristin): + // The dynamic cast is necessary due to virtual inheritance. Otherwise, + // we would have used static cast. + casted_( + dynamic_cast( + instance.get() + ) + ) { + // Intentionally empty. +} + +void IteratorOverListOfPrimitives::Start() { + state_ = 0; + Execute(); +} + +void IteratorOverListOfPrimitives::Next() { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to move IteratorOverListOfPrimitives, " + "but it was done." + ); + } + #endif + + Execute(); +} + +bool IteratorOverListOfPrimitives::Done() const { + return done_; +} + +const std::shared_ptr& IteratorOverListOfPrimitives::Get() const { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to get from IteratorOverListOfPrimitives, " + "but the iterator was done." + ); + } + #endif + + return item_; +} + +long IteratorOverListOfPrimitives::Index() const { + #ifdef DEBUG + if (Done() && index_ != -1) { + throw std::logic_error( + common::Concat( + "Expected index to be -1 " + "from a done IteratorOverListOfPrimitives, " + "but got: ", + std::to_string(index_) + ) + ); + } + #endif + + return index_; +} + +void IteratorOverListOfPrimitives::PrependToPath( + Path* path +) const { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to prepend to path from IteratorOverListOfPrimitives, " + "but the iterator was done." + ); + } + #endif + + if (cursor_.has_value()) { + path->segments.emplace_front( + common::make_unique(*cursor_) + ); + } + + #ifdef DEBUG + if (!property_.has_value()) { + throw std::logic_error( + "You want to prepend to path from IteratorOverListOfPrimitives, " + "but the property_ has not been set to a value." + ); + } + #endif + + path->segments.emplace_front( + common::make_unique(*property_) + ); +} + +std::unique_ptr IteratorOverListOfPrimitives::Clone() const { + return common::make_unique(*this); +} + +void IteratorOverListOfPrimitives::Execute() { + while (true) { + switch (state_) { + case 0: { + property_.reset(); + item_ = nullptr; + index_ = -1; + done_ = false; + + cursor_.reset(); + + property_ = Property::kStrings; + + cursor_ = 0; + } + + case 1: { + if (!(*cursor_ < casted_->strings().size())) { + state_ = 3; + continue; + } + + const std::vector& the_strings( + casted_->strings() + ); + + item_ = std::move( + std::static_pointer_cast( + the_strings[*cursor_] + ) + ); + ++index_; + + state_ = 2; + return; + } + + case 2: { + ++(*cursor_); + + state_ = 1; + continue; + } + + case 3: { + cursor_.reset(); + + property_ = Property::kIntegers; + + cursor_ = 0; + } + + case 4: { + if (!(*cursor_ < casted_->integers().size())) { + state_ = 6; + continue; + } + + const std::vector& the_integers( + casted_->integers() + ); + + item_ = std::move( + std::static_pointer_cast( + the_integers[*cursor_] + ) + ); + ++index_; + + state_ = 5; + return; + } + + case 5: { + ++(*cursor_); + + state_ = 4; + continue; + } + + case 6: { + cursor_.reset(); + + property_ = Property::kBooleans; + + cursor_ = 0; + } + + case 7: { + if (!(*cursor_ < casted_->booleans().size())) { + state_ = 9; + continue; + } + + const std::vector& the_booleans( + casted_->booleans() + ); + + item_ = std::move( + std::static_pointer_cast( + the_booleans[*cursor_] + ) + ); + ++index_; + + state_ = 8; + return; + } + + case 8: { + ++(*cursor_); + + state_ = 7; + continue; + } + + case 9: { + cursor_.reset(); + + property_ = Property::kClasses; + + cursor_ = 0; + } + + case 10: { + if (!(*cursor_ < casted_->classes().size())) { + state_ = 12; + continue; + } + + const std::vector< + std::shared_ptr + >& the_classes( + casted_->classes() + ); + + item_ = std::move( + std::static_pointer_cast( + the_classes[*cursor_] + ) + ); + ++index_; + + state_ = 11; + return; + } + + case 11: { + ++(*cursor_); + + state_ = 10; + continue; + } + + case 12: { + cursor_.reset(); + + done_ = true; + index_ = -1; + + // We invalidate the state since we reached the end of the routine. + state_ = 13; + return; + } + + default: + throw std::logic_error( + common::Concat( + "Invalid state_: ", + std::to_string(state_) + ) + ); + } + } +} + +// endregion + +/** + * This iterator is always done. + * + * It is used for efficient comparisons against end-of-descent. + */ +class AlwaysDoneIterator : public impl::IIterator { + public: + void Start() override { + // Intentionally empty. + } + + void Next() override { + throw std::logic_error( + "You want to move an AlwaysDoneIterator, " + "but the iterator is always done, as its name suggests." + ); + } + + bool Done() const override { + return true; + } + + const std::shared_ptr& Get() const override { + throw std::logic_error( + "You want to get from an AlwaysDoneIterator, " + "but the iterator is always done, as its name suggests." + ); + } + + std::unique_ptr Clone() const override { + return common::make_unique(*this); + }; + + void PrependToPath(Path*) const override { + throw std::logic_error( + "You want to prepend to path from an AlwaysDoneIterator, " + "but the iterator is always done, as its name suggests." + ); + } + + long Index() const override { + return -1; + } + + ~AlwaysDoneIterator() override = default; +}; // class AlwaysDoneIterator + +/** + * Produce a non-recursive iterator over the instance given its runtime model type. + */ +std::unique_ptr NewNonRecursiveIterator( + const std::shared_ptr& instance +) { + switch (instance->model_type()) { + case types::ModelType::kMyClass: + return common::make_unique( + instance + ); + case types::ModelType::kListOfPrimitives: + return common::make_unique( + instance + ); + default: + throw std::logic_error( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast(instance->model_type()) + ) + ) + ); + } +} + +// endregion Non-recursive iteration + +// region Recursive iteration + +/** + * Iterate recursively over the instance, including the instance in the iteration. + * + * This is a realisation of the following pseudo-code: + * \code + * stack = new Stack(); + * stack.push(instance); + * while not stack.empty(): + * instance = stack.pop() + * yield instance + * + * it = new_non_recursive_iterator(instance) + * while not it.done(): + * yield recursively from it.get() + * it.next() + * \endcode + */ +class RecursiveInclusiveIterator : public impl::IIterator { + public: + RecursiveInclusiveIterator( + const std::shared_ptr& instance + ); + + RecursiveInclusiveIterator( + const RecursiveInclusiveIterator& other + ); + RecursiveInclusiveIterator( + RecursiveInclusiveIterator&& other + ); + RecursiveInclusiveIterator& operator=( + const RecursiveInclusiveIterator& other + ); + RecursiveInclusiveIterator& operator=( + RecursiveInclusiveIterator&& other + ); + + void Start() override; + void Next() override; + bool Done() const override; + const std::shared_ptr& Get() const override; + long Index() const override; + void PrependToPath(Path* path) const override; + std::unique_ptr Clone() const override; + ~RecursiveInclusiveIterator() override = default; + + private: + // The instance_ needs to be a pointer so that we can re-assign it in + // the constructors and assignment operations. + const std::shared_ptr* instance_; + + // Iterator over the instances referenced from this instance + // in the outer loop + std::unique_ptr non_recursive_iterator_; + + // Iterator for recursion into the reference referenced from this instance + // in the inner loop + std::unique_ptr recursive_iterator_; + + const std::shared_ptr* item_; + + bool done_; + long index_; + size_t state_; + + void Execute(); +}; // class RecursiveInclusiveIterator + +/** + * Iterate recursively over the instance, excluding the instance in the iteration. + * + * This is a realisation of the following pseudo-code: + * \code + * stack = new Stack(); + * stack.push(instance); + * while not stack.empty(): + * some_instance = stack.pop() + * if some_instance is not instance: + * yield some_instance + * + * it = new_non_recursive_iterator(some_instance) + * while not it.done(): + * yield recursively from it.get() + * it.next() + * \endcode + */ +class RecursiveExclusiveIterator : public impl::IIterator { + public: + RecursiveExclusiveIterator( + const std::shared_ptr& instance + ); + + void Start() override; + void Next() override; + bool Done() const override; + const std::shared_ptr& Get() const override; + long Index() const override; + void PrependToPath(Path* path) const override; + std::unique_ptr Clone() const override; + ~RecursiveExclusiveIterator() override = default; + + private: + RecursiveInclusiveIterator inclusive_iterator_; +}; // class RecursiveExclusiveIterator + +// region RecursiveInclusiveIterator implementation + +RecursiveInclusiveIterator::RecursiveInclusiveIterator( + const std::shared_ptr& instance +) : instance_(&instance), item_(nullptr), index_(-1) { + // Intentionally empty. +} + +RecursiveInclusiveIterator::RecursiveInclusiveIterator( + const RecursiveInclusiveIterator& other +) { + instance_ = other.instance_; + non_recursive_iterator_ = (other.non_recursive_iterator_ == nullptr) + ? nullptr + : other.non_recursive_iterator_->Clone(); + recursive_iterator_ = (other.recursive_iterator_ == nullptr) + ? nullptr + : other.recursive_iterator_->Clone(); + item_ = other.item_; + done_ = other.done_; + index_ = other.index_; + state_ = other.state_; +} + +RecursiveInclusiveIterator::RecursiveInclusiveIterator( + RecursiveInclusiveIterator&& other +) { + instance_ = other.instance_; + non_recursive_iterator_ = std::move(other.non_recursive_iterator_); + recursive_iterator_ = std::move(other.recursive_iterator_); + item_ = other.item_; + done_ = other.done_; + index_ = other.index_; + state_ = other.state_; +} + +RecursiveInclusiveIterator& RecursiveInclusiveIterator::operator=( + const RecursiveInclusiveIterator& other +) { + return *this = RecursiveInclusiveIterator(other); +} + +RecursiveInclusiveIterator& RecursiveInclusiveIterator::operator=( + RecursiveInclusiveIterator&& other +) { + if (this != &other) { + instance_ = other.instance_; + non_recursive_iterator_ = std::move(other.non_recursive_iterator_); + recursive_iterator_ = std::move(other.recursive_iterator_); + item_ = other.item_; + done_ = other.done_; + index_ = other.index_; + state_ = other.state_; + } + + return *this; +} + +void RecursiveInclusiveIterator::Start() { + state_ = 0; + Execute(); + + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "Expected RecursiveInclusiveIterator not to be done at start, but it was." + ); + } + + if (Index() !== 0) { + throw std::logic_error( + common::Concat( + "Expected RecursiveInclusiveIterator::Index() to be 0 on Start()" + ", but got ", + std::to_string(Index()) + ) + ); + } + + const std::shared_ptr& current_item(Get()); + if (current_item == nullptr) { + throw std::logic_error( + "Unexpected null pointer from Get() at the end of " + "RecursiveInclusiveIterator::Start" + ); + } + + if (current_item.get() != instance_.get()) { + throw std::logic_error( + common::Concat( + "Expected the current item to point to the instance " + "at the end of RecursiveInclusiveIterator::Start, " + "but got ", + std::to_string(current_item.get()), + " from Get() instead of ", + std::to_string(instance_.get()) + ) + ); + } + #endif +} + +void RecursiveInclusiveIterator::Next() { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to move a RecursiveInclusiveIterator, but it was done." + ); + } + #endif + + Execute(); +} + +bool RecursiveInclusiveIterator::Done() const { + return done_; +} + +const std::shared_ptr& RecursiveInclusiveIterator::Get() const { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to get from RecursiveInclusiveIterator, but it was done." + ); + } + + if (item_ == nullptr) { + throw std::logic_error( + "You want to get from a RecursiveInclusiveIterator, " + "but item_ has not been set." + ); + } + #endif + + return *item_; +} + +long RecursiveInclusiveIterator::Index() const { + #ifdef DEBUG + if (Done() && index_ != -1) { + throw std::logic_error( + common::Concat( + "Expected index to be -1 on a done RecursiveInclusiveIterator, " + "but got: ", + std::to_string(index_) + ) + ); + } + #endif + + return index_; +} + +void RecursiveInclusiveIterator::PrependToPath(Path* path) const { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to prepend to path from RecursiveInclusiveIterator, " + "but the iterator was done." + ); + } + #endif + + if (Index() == 0) { + // Index set to 0 indicates that the iterator points to the instance itself. + // Therefore, there is nothing to prepend to the path. + return; + } + + if (recursive_iterator_ != nullptr) { + recursive_iterator_->PrependToPath(path); + } + + if (non_recursive_iterator_ != nullptr) { + non_recursive_iterator_->PrependToPath(path); + } +} + +std::unique_ptr RecursiveInclusiveIterator::Clone() const { + return common::make_unique(*this); +} + +void RecursiveInclusiveIterator::Execute() { + while (true) { + switch (state_) { + case 0: { + item_ = instance_; + index_ = 0; + done_ = false; + non_recursive_iterator_.reset(nullptr); + recursive_iterator_.reset(nullptr); + + state_ = 1; + return; + } + + case 1: { + non_recursive_iterator_ = NewNonRecursiveIterator( + *instance_ + ); + + non_recursive_iterator_->Start(); + } + + case 2: { + if (!(!non_recursive_iterator_->Done())) { + state_ = 7; + continue; + } + + item_ = &(non_recursive_iterator_->Get()); + ++index_; + + state_ = 3; + return; + } + + case 3: { + recursive_iterator_ = std::move( + common::make_unique( + *item_ + ) + ); + + recursive_iterator_->Start(); + } + + case 4: { + if (!(!recursive_iterator_->Done())) { + state_ = 6; + continue; + } + + item_ = &(recursive_iterator_->Get()); + ++index_; + + state_ = 5; + return; + } + + case 5: { + recursive_iterator_->Next(); + + state_ = 4; + continue; + } + + case 6: { + recursive_iterator_.reset(nullptr); + + non_recursive_iterator_->Next(); + + state_ = 2; + continue; + } + + case 7: { + non_recursive_iterator_.reset(nullptr); + done_ = true; + index_ = -1; + + // We invalidate the state since we reached the end of the routine. + state_ = 8; + return; + } + + default: + throw std::logic_error( + common::Concat( + "Invalid state_: ", + std::to_string(state_) + ) + ); + } + } +} + +// endregion RecursiveInclusiveIterator implementation + +// region RecursiveExclusiveIterator implementation + +RecursiveExclusiveIterator::RecursiveExclusiveIterator( + const std::shared_ptr& instance +) : inclusive_iterator_(instance) { + // Intentionally empty. +} + +void RecursiveExclusiveIterator::Start() { + inclusive_iterator_.Start(); + + #ifdef DEBUG + if (inclusive_iterator_.Done()) { + throw std::logic_error( + "Expected the inclusive iterator to be not-done immediately after start, " + "as the first item is expected to point to the instance itself, " + "but the inclusive iterator was done." + ); + } + #endif + + // Simply skip the instance in the very first yield. + inclusive_iterator_.Next(); +} + +void RecursiveExclusiveIterator::Next() { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to move a RecursiveExclusiveIterator, but it was done." + ); + } + #endif + + inclusive_iterator_.Next(); +} + +bool RecursiveExclusiveIterator::Done() const { + return inclusive_iterator_.Done(); +} + +const std::shared_ptr& RecursiveExclusiveIterator::Get() const { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to get from RecursiveExclusiveIterator, but it was done." + ); + } + #endif + + return inclusive_iterator_.Get(); +} + +long RecursiveExclusiveIterator::Index() const { + if (inclusive_iterator_.Done()) { + return -1; + } + + return inclusive_iterator_.Index() - 1; +} + +void RecursiveExclusiveIterator::PrependToPath(Path* path) const { + inclusive_iterator_.PrependToPath(path); +} + +std::unique_ptr RecursiveExclusiveIterator::Clone() const { + return common::make_unique(*this); +} + +// endregion RecursiveExclusiveIterator implementation + +// endregion Recursive iteration + +// region Iterator facade + +Iterator::Iterator( + const Iterator& other +) : implementation_(other.implementation_->Clone()) { + // Intentionally empty. +} + +Iterator::Iterator( + Iterator&& other +) : implementation_(std::move(other.implementation_)) { + // Intentionally empty. +} + +Iterator& Iterator::operator=(const Iterator& other) { + return *this = Iterator(other); +} + +Iterator& Iterator::operator=(Iterator&& other) { + if (this != &other) { + this->implementation_ = std::move(other.implementation_); + } + + return *this; +} + +const std::shared_ptr& Iterator::operator*() const { + if (implementation_->Done()) { + throw std::logic_error( + "You want to dereference a completed iterator." + ); + } + + return implementation_->Get(); +} + +const std::shared_ptr* Iterator::operator->() { + if (implementation_->Done()) { + throw std::logic_error( + "You want to dereference a completed iterator." + ); + } + + return &(implementation_->Get()); +} + +// Prefix increment +Iterator& Iterator::operator++() { + if (implementation_->Done()) { + throw std::logic_error( + "You want to move a completed iterator." + ); + } + + implementation_->Next(); + return *this; +} + +// Postfix increment +Iterator Iterator::operator++(int) { + Iterator result(*this); + ++(*this); + return result; +} + +bool operator==(const Iterator& a, const Iterator& b) { + return a.implementation_->Index() == b.implementation_->Index(); +} + +bool operator!=(const Iterator& a, const Iterator& b) { + return a.implementation_->Index() != b.implementation_->Index(); +} + +Path MaterializePath(const Iterator& iterator) { + if (iterator.implementation_->Done()) { + throw std::logic_error( + "You want to materialize path of a completed iterator." + ); + } + + Path path; + iterator.implementation_->PrependToPath(&path); + return path; +} + +void PrependToPath(const Iterator& iterator, Path* path) { + if (iterator.implementation_->Done()) { + throw std::logic_error( + "You want to prepend a path of a completed iterator." + ); + } + + iterator.implementation_->PrependToPath(path); +} + +// endregion Iterator facade + +// region Descents + +// region Descent + +// NOTE (mristin): +// We have to make a copy of the pointer since we would lose otherwise +// in range-based `for` loops, +// see: https://stackoverflow.com/questions/29990045/temporary-lifetime-in-range-for-expression +Descent::Descent( + std::shared_ptr instance +) : instance_(std::move(instance)) { + // Intentionally empty. +} + +Iterator Descent::begin() const { + std::unique_ptr it_impl( + std::move( + common::make_unique(instance_) + ) + ); + + it_impl->Start(); + + // NOTE(mristin): + // We short-circuit here for memory frugality, + // as we can immediately dispose it_impl. + if (it_impl->Done()) { + return end(); + } + + return Iterator(std::move(it_impl)); +} + +const Iterator& Descent::end() const { + static Iterator iterator(common::make_unique()); + return iterator; +} + +// endregion Descent + +// region DescentOnce + +// NOTE (mristin): +// We have to make a copy of the pointer since we would lose otherwise +// in range-based `for` loops, +// see: https://stackoverflow.com/questions/29990045/temporary-lifetime-in-range-for-expression +DescentOnce::DescentOnce( + std::shared_ptr instance +) : instance_(std::move(instance)) { + // Intentionally empty. +} + +Iterator DescentOnce::begin() const { + std::unique_ptr it_impl( + NewNonRecursiveIterator(instance_) + ); + + it_impl->Start(); + + // NOTE(mristin): + // We short-circuit here for efficiency, as we can immediately dispose it_impl. + if (it_impl->Done()) { + return Iterator(std::move(common::make_unique())); + } + + return Iterator(std::move(it_impl)); +} + +const Iterator& DescentOnce::end() const { + static Iterator iterator(common::make_unique()); + return iterator; +} + +// endregion DescentOnce + +// endregion Descents + +} // namespace iteration +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/iteration.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/iteration.hpp new file mode 100644 index 000000000..9de87ab7a --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/iteration.hpp @@ -0,0 +1,338 @@ +#ifndef AAS_CORE_AAS_3_0_ITERATION_GUARD_ +#define AAS_CORE_AAS_3_0_ITERATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup iteration Define functions and structures to iterate over instances. + * @{ +*/ +namespace iteration { + +// region Pathing + +/** + * Define the properties over all the classes to compactly represent the paths. + */ +enum class Property : std::uint32_t { + kBooleans = 0, + kClasses = 1, + kIntegers = 2, + kStrings = 3 +}; + +std::wstring PropertyToWstring( + Property property +); + +/** + * Represent a segment of a path to some value. + */ +class ISegment { + public: + virtual std::wstring ToWstring() const = 0; + virtual std::unique_ptr Clone() const = 0; + virtual ~ISegment() = default; +}; // class ISegment + +/** + * Represent a property access on a path. + */ +struct PropertySegment : public ISegment { + /** + * Enumeration of the property + */ + Property property; + + PropertySegment( + Property a_property + ); + + std::wstring ToWstring() const override; + std::unique_ptr Clone() const override; + + ~PropertySegment() override = default; +}; // struct PropertySegment + +/** + * Represent an index access on a path. + */ +struct IndexSegment : public ISegment { + /** + * Index of the item + */ + size_t index; + + explicit IndexSegment( + size_t an_index + ); + + std::wstring ToWstring() const override; + std::unique_ptr Clone() const override; + + ~IndexSegment() override = default; +}; // struct IndexSegment + +/** + * \brief Represent a path to some value. + * + * This is a path akin to C++ expressions. It is not to be confused with different + * paths used in the specification. This path class is meant to help with reporting. + * For example, we can use this path to let the user know when there is + * a verification error in a model which can concern instances, but also properties + * and items in the lists. + */ +struct Path { + // NOTE (mristin): + // We did not implement the reflection at the moment since we did not have a use + // case for it. If you need reflection, please contact the developers. It should + // be a small step going from paths to dereferencing to getters and setters. + + std::deque > segments; + + Path(); + Path(const Path& other); + Path(Path&& other); + Path& operator=(const Path& other); + Path& operator=(Path&& other); + + std::wstring ToWstring() const; +}; // struct Path + +// endregion Pathing + +// region Iterators and descent + +/// \cond HIDDEN +namespace impl { +class IIterator { + public: + virtual void Start() = 0; + virtual void Next() = 0; + virtual bool Done() const = 0; + virtual const std::shared_ptr& Get() const = 0; + virtual long Index() const = 0; + + /// Prepend the segments to the path reflecting where this iterator points to. + virtual void PrependToPath(Path* path) const = 0; + + virtual std::unique_ptr Clone() const = 0; + + virtual ~IIterator() = default; +}; // class IIterator +} // namespace impl +/// \endcond + +/** + * \brief Iterate over an AAS instance. + * + * Unlike STL, this is not a light-weight iterator. We implement + * a "yielding" iterator by leveraging code generation so that we always keep + * the model stack as well as the properties iterated thus far. + * + * This means that copy-construction and equality comparisons are much more heavy-weight + * than you'd usually expect from an STL iterator. For example, if you want to sort + * model instances, you are most probably faster if you populate a vector, and then + * sort the vector. + * + * Also, given that this iterator is not light-weight, you should in almost all cases + * avoid the postfix increment (it++) and prefer the prefix one (++it) as the postfix + * increment would create an iterator copy every time. + * + * The value of the iterator is intentionally constant reference to a shared pointer. + * This merely means that you can not change the pointer while you are + * iterating. The pointed instances, however, is freely mutable. This way you can make + * further shared pointers, or include the pointed instances in other collections + * different from the original container. On the other hand, the normal case, where + * the pointer is only de-referenced, remains efficient as no copy of + * the shared pointer is created. + * + * We follow the C++ standard, and assume that comparison between the two iterators + * over two different instances results in undefined behavior. See + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html and + * https://stackoverflow.com/questions/4657513/comparing-iterators-from-different-containers. + * + * Since we use const references to shared pointers here you can also share ownership + * over instances in your own external containers. Making a copy of a shared pointer + * will automatically increase reference count, even though there is a constant + * reference. Since we do not make copies of the shared pointers, it is very important + * that the given shared pointers outlive the iteration, lest cause undefined behavior. + * + * Changing the references during the iteration invalidates the iterators and + * results in undefined behavior. This is similar to many of the containers in the STL, + * see: https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers + * + * See these StackOverflow questions for performance related to shared pointers and + * constant references to shared pointers (copying versus referencing): + * * https://stackoverflow.com/questions/12002480/passing-stdshared-ptr-to-constructors/12002668#12002668 + * * https://stackoverflow.com/questions/3310737/should-we-pass-a-shared-ptr-by-reference-or-by-value + * * https://stackoverflow.com/questions/37610494/passing-const-shared-ptrt-versus-just-shared-ptrt-as-parameter + * + * The following StackOverflow question and answers go into more detail how const-ness + * and shared pointers fit together: + * https://stackoverflow.com/questions/36271663/why-does-copying-a-const-shared-ptr-not-violate-const-ness + */ +class Iterator { + using iterator_category = std::forward_iterator_tag; + /// The difference is meaningless, but has to be defined. + using difference_type = std::ptrdiff_t; + using value_type = std::shared_ptr; + using pointer = const std::shared_ptr*; + using reference = const std::shared_ptr&; + + public: + Iterator(const Iterator& other); + Iterator(Iterator&& other); + + Iterator& operator=(const Iterator& other); + Iterator& operator=(Iterator&& other); + + reference operator*() const; + pointer operator->(); + + // Prefix increment + Iterator& operator++(); + + // Postfix increment + Iterator operator++(int); + + friend bool operator==(const Iterator& a, const Iterator& b); + friend bool operator!=(const Iterator& a, const Iterator& b); + + friend class Descent; + friend class DescentOnce; + friend Path MaterializePath(const Iterator& iterator); + friend void PrependToPath(const Iterator& iterator, Path* path); + + private: + explicit Iterator( + std::unique_ptr implementation + ) : + implementation_(std::move(implementation)) { + // Intentionally empty. + } + + std::unique_ptr implementation_; +}; + +bool operator==(const Iterator& a, const Iterator& b); + +bool operator!=(const Iterator& a, const Iterator& b); + +/** + * \brief Materialize the path that the \p iterator points to. + * + * We assume that you always want a copy of the path, rather than inspect + * the path during the iteration. + * + * \param iterator for which we want to materialize the path + * \return Path referring to the pointed instance + */ +Path MaterializePath(const Iterator& iterator); + +/** + * Build a facade over an instance to iterate over instances referenced from it. + */ +class IDescent { + public: + virtual Iterator begin() const = 0; + virtual const Iterator& end() const = 0; + virtual ~IDescent() = default; +}; // class IDescent + +/** + * \brief Provide a recursive iterable over all the instances referenced from + * an instance. + * + * Please see the notes in the class Iterator regarding the constant reference to + * a shared pointer. In short, the instance should outlive the descent, so make + * sure you do not destroy it during the descent. + * + * Range-based loops should fit the vast majority of the use cases: + * \code + * std::shared_ptr env = ...; + * for ( + * const std::shared_ptr& instance + * : Descent(env) + * ) { + * do_something(instance); + * } + * \endcode + * + * \param that instance to be iterated over recursively + * \return Iterable over referenced instances + */ +class Descent : public IDescent { + public: + Descent( + std::shared_ptr instance + ); + + Iterator begin() const override; + const Iterator& end() const override; + + ~Descent() override = default; + + private: + std::shared_ptr instance_; +}; // class Descent + +/** + * \brief Provide a non-recursive iterable over the instances referenced from + * an instance. + * + * Please see the notes in the class Iterator regarding the constant reference to + * a shared pointer. In short, the instance should outlive the descent, so make + * sure you do not destroy it during the descent. + * + * Range-based loops should fit the vast majority of the use cases: + * \code + * std::shared_ptr env = ...; + * for ( + * const std::shared_ptr& instance + * : DescentOnce(env) + * ) { + * do_something(instance); + * } + * \endcode + */ +class DescentOnce : public IDescent { + public: + DescentOnce( + std::shared_ptr instance + ); + + Iterator begin() const override; + const Iterator& end() const override; + + ~DescentOnce() override = default; + + private: + std::shared_ptr instance_; +}; // class DescentOnce + +// endregion Iterators and descent + +} // namespace iteration +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_ITERATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.cpp new file mode 100644 index 000000000..25f1827c2 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.cpp @@ -0,0 +1,1587 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/jsonization.hpp" +#include "aas_core/aas_3_0/stringification.hpp" +#include "aas_core/aas_3_0/wstringification.hpp" + +#pragma warning(push, 0) +#include +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { +namespace jsonization { + +// region PropertySegment + +PropertySegment::PropertySegment( + std::wstring a_name +) : + name(std::move(a_name)) { + // Intentionally empty. +} + +std::wstring PropertySegment::ToWstring() const { + return common::Concat( + L".", + name + ); +} + +std::unique_ptr PropertySegment::Clone() const { + return common::make_unique(*this); +} + +// endregion PropertySegment + +// region IndexSegment + +IndexSegment::IndexSegment( + size_t an_index +) : + index(an_index) { + // Intentionally empty. +} + +std::wstring IndexSegment::ToWstring() const { + return common::Concat( + L"[", + std::to_wstring(index), + L"]" + ); +} + +std::unique_ptr IndexSegment::Clone() const { + return common::make_unique(*this); +} + +// endregion IndexSegment + +// region struct Path + +Path::Path() { + // Intentionally empty. +} + +Path::Path(const Path& other) { + for (const std::unique_ptr& segment : other.segments) { + segments.emplace_back(segment->Clone()); + } +} + +Path::Path(Path&& other) { + segments = std::move(other.segments); +} + +Path& Path::operator=(const Path& other) { + segments.clear(); + for (const std::unique_ptr& segment : other.segments) { + segments.emplace_back(segment->Clone()); + } + return *this; +} + +Path& Path::operator=(Path&& other) { + if (this != &other) { + segments = std::move(other.segments); + } + return *this; +} + +std::wstring Path::ToWstring() const { + if (segments.empty()) { + return L""; + } + + std::deque parts; + for (const std::unique_ptr& segment : segments ) { + parts.emplace_back(segment->ToWstring()); + } + + size_t out_len = 0; + for (const std::wstring& part : parts) { + out_len += part.size(); + } + + std::wstring out; + out.reserve(out_len); + for (const std::wstring& part : parts) { + out.append(part); + } + + return out; +} + +// endregion struct Path + +// region De-serialization + +// region class DeserializationError + +DeserializationError::DeserializationError( + std::wstring a_cause +) : + cause(a_cause) { + // Intentionally empty. +} + +DeserializationError::DeserializationError( + std::wstring a_cause, + Path a_path +) : + cause(a_cause), + path(a_path) { + // Intentionally empty. +} + +// endregion class DeserializationError + +std::pair< + common::optional, + common::optional +> DeserializeBool( + const nlohmann::json& json +) { + if (!json.is_boolean()) { + std::wstring message = common::Concat( + L"Expected a boolean, but got a value of type: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + return std::make_pair< + common::optional, + common::optional + >( + json.get(), + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> DeserializeInt64( + const nlohmann::json& json +) { + if (!json.is_number()) { + std::wstring message = common::Concat( + L"Expected an integer number, but got a value of type: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + static_assert( + std::is_same::value, + "Expected nlohmann::json::number_integer_t to equal int64_t, " + "but it does not." + ); + + if (json.is_number_integer()) { + return std::make_pair< + common::optional, + common::optional + >( + json.get(), + common::nullopt + ); + } + + if (json.is_number_unsigned()) { + std::wstring message = common::Concat( + L"Expected a 64-bit integer number, " + L"but got an unsigned integer number which does not fit in that range: ", + std::to_wstring(json.get()) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + // NOTE (mristin): + // We have to check that the number is an integer even though it can + // not be stored in int64_t in order to give an informative message. + + const nlohmann::json::number_float_t number( + json.get() + ); + + nlohmann::json::number_float_t integer_part; + const bool is_integer( + std::modf(number, &integer_part) == 0 + ); + if (is_integer) { + std::wstring message = common::Concat( + L"Expected a 64-bit integer number, " + L"but got an integer number which does not fit in that range: ", + std::to_wstring(number) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } else { + std::wstring message = common::Concat( + L"Expected a 64-bit integer number, " + L"but got a non-integer number: ", + std::to_wstring(number) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } +} + +std::pair< + common::optional, + common::optional +> DeserializeDouble( + const nlohmann::json& json +) { + if (!json.is_number()) { + std::wstring message = common::Concat( + L"Expected a number, but got a value of type: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + static_assert( + std::is_same::value, + "Expected nlohmann::json::number_float_t to equal double, " + "but it does not." + ); + + return std::make_pair< + common::optional, + common::optional + >( + json.get(), + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> DeserializeWstring( + const nlohmann::json& json +) { + if (!json.is_string()) { + std::wstring message = common::Concat( + L"Expected a string, but got a value of type: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + return std::make_pair< + common::optional, + common::optional + >( + common::Utf8ToWstring(*(json.get_ptr())), + common::nullopt + ); +} + +std::pair< + common::optional >, + common::optional +> DeserializeByteArray( + const nlohmann::json& json +) { + if (!json.is_string()) { + std::wstring message = common::Concat( + L"Expected a base64-encoded byte array as a string, " + L"but got a value of type: ", + common::Utf8ToWstring(json.type_name()) + );; + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + common::expected< + std::vector, + std::string + > bytes = stringification::Base64Decode( + *(json.get_ptr()) + ); + + if (!bytes.has_value()) { + std::wstring message = common::Concat( + L"Failed to base64-decode the bytes from a string: ", + common::Utf8ToWstring(bytes.error()) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + return std::make_pair< + common::optional >, + common::optional + >( + std::move(*bytes), + common::nullopt + ); +} + +/** + * Get the property `modelType` from the JSON value expected as a JSON object. + */ +std::pair< + const std::string*, + common::optional +> GetModelTypeFrom( + const nlohmann::json& json +) { + if (!json.is_object()) { + std::wstring message = common::Concat( + L"Expected an object, but got: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + const std::string*, + common::optional + >( + nullptr, + common::make_optional( + message + ) + ); + } + + if (!json.contains("modelType")) { + return std::make_pair< + const std::string*, + common::optional + >( + nullptr, + common::make_optional( + L"The required property modelType is missing" + ) + ); + } + + const nlohmann::json& model_type_prop = json["modelType"]; + if (!model_type_prop.is_string()) { + std::wstring message = common::Concat( + L"Expected modelType to be a string, but got: ", + common::Utf8ToWstring(model_type_prop.type_name()) + ); + + common::optional error( + common::make_optional( + message + ) + ); + error->path.segments.emplace_front( + common::make_unique( + L"modelType" + ) + ); + + // NOTE (mristin): + // We have to explicitly use the constructor instead of std::make_pair + // as `const std::string*` can not be automatically converted to a rvalue. + return std::pair< + const std::string*, + common::optional + >( + nullptr, + error + ); + } + + static_assert( + std::is_same::value, + "Expected nlohmann::json::string_t to equal std::string, but it does not." + ); + + const std::string* model_type( + model_type_prop.get_ptr() + ); + + // NOTE (mristin): + // We have to explicitly use the constructor instead of std::make_pair + // as `const std::string*` can not be automatically converted to a rvalue. + return std::pair< + const std::string*, + common::optional + >( + model_type, + common::nullopt + ); +} + +/** + * \brief Deserialize concretely an instance + * of types::IMyClass. + * + * \param json value to be de-serialized + * \param additional_properties if not set, check that \p json contains + * no additional properties + * \return the deserialized instance, or an error, if any + */ +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> DeserializeMyClass( + const nlohmann::json& json, + bool additional_properties +); + +/** + * \brief Deserialize concretely an instance + * of types::IListOfPrimitives. + * + * \param json value to be de-serialized + * \param additional_properties if not set, check that \p json contains + * no additional properties + * \return the deserialized instance, or an error, if any + */ +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> DeserializeListOfPrimitives( + const nlohmann::json& json, + bool additional_properties +); + +std::set kPropertiesInMyClass = { + +}; + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> DeserializeMyClass( + const nlohmann::json& json, + bool additional_properties +) { + if (!json.is_object()) { + std::wstring message = common::Concat( + L"Expected an object, but got: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + if (!additional_properties) { + for (const auto& key_val : json.items()) { + auto it( + kPropertiesInMyClass.find(key_val.key()) + ); + if (it == kPropertiesInMyClass.end()) { + std::wstring message = common::Concat( + L"Unexpected additional property: ", + common::Utf8ToWstring(key_val.key()) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + } + } + + return std::make_pair( + common::make_optional< + std::shared_ptr + >( + // NOTE (mristin): + // We deliberately do not use std::make_shared here to avoid an unnecessary + // upcast. + new types::MyClass() + ), + common::nullopt + ); +} + +std::set kPropertiesInListOfPrimitives = { + "strings", + "integers", + "booleans", + "classes" +}; + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> DeserializeListOfPrimitives( + const nlohmann::json& json, + bool additional_properties +) { + if (!json.is_object()) { + std::wstring message = common::Concat( + L"Expected an object, but got: ", + common::Utf8ToWstring(json.type_name()) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + if (!additional_properties) { + for (const auto& key_val : json.items()) { + auto it( + kPropertiesInListOfPrimitives.find(key_val.key()) + ); + if (it == kPropertiesInListOfPrimitives.end()) { + std::wstring message = common::Concat( + L"Unexpected additional property: ", + common::Utf8ToWstring(key_val.key()) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + } + } + + // region Check required properties + + if (!json.contains("strings")) { + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + L"The required property strings is missing" + ) + ); + } + + if (!json.contains("integers")) { + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + L"The required property integers is missing" + ) + ); + } + + if (!json.contains("booleans")) { + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + L"The required property booleans is missing" + ) + ); + } + + if (!json.contains("classes")) { + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + common::make_optional( + L"The required property classes is missing" + ) + ); + } + + // endregion Check required properties + + // region Initialization + + common::optional error; + + common::optional > the_strings; + + common::optional > the_integers; + + common::optional > the_booleans; + + common::optional< + std::vector< + std::shared_ptr + > + > the_classes; + + // endregion Initialization + + // region De-serialize strings + + const nlohmann::json& json_strings( + json["strings"] + ); + if (!json_strings.is_array()) { + error = common::make_optional( + common::Concat( + L"Expected an array, but got: ", + common::Utf8ToWstring( + json_strings.type_name() + ) + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"strings" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_strings = common::make_optional< + std::vector< + std::shared_ptr + > + >(); + + the_strings->reserve(json_strings.size()); + + size_t index_strings = 0; + + for ( + const nlohmann::json& item + : json_strings + ) { + common::optional< + std::shared_ptr + > deserialized; + + std::tie( + deserialized, + error + ) = DeserializeWstring( + item, + additional_properties + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_strings + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"strings" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_strings->emplace_back( + std::move(*deserialized) + ); + + ++index_strings; + } + + // endregion De-serialize strings + + // region De-serialize integers + + const nlohmann::json& json_integers( + json["integers"] + ); + if (!json_integers.is_array()) { + error = common::make_optional( + common::Concat( + L"Expected an array, but got: ", + common::Utf8ToWstring( + json_integers.type_name() + ) + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"integers" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_integers = common::make_optional< + std::vector< + std::shared_ptr + > + >(); + + the_integers->reserve(json_integers.size()); + + size_t index_integers = 0; + + for ( + const nlohmann::json& item + : json_integers + ) { + common::optional< + std::shared_ptr + > deserialized; + + std::tie( + deserialized, + error + ) = DeserializeInt64( + item, + additional_properties + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_integers + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"integers" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_integers->emplace_back( + std::move(*deserialized) + ); + + ++index_integers; + } + + // endregion De-serialize integers + + // region De-serialize booleans + + const nlohmann::json& json_booleans( + json["booleans"] + ); + if (!json_booleans.is_array()) { + error = common::make_optional( + common::Concat( + L"Expected an array, but got: ", + common::Utf8ToWstring( + json_booleans.type_name() + ) + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"booleans" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_booleans = common::make_optional< + std::vector< + std::shared_ptr + > + >(); + + the_booleans->reserve(json_booleans.size()); + + size_t index_booleans = 0; + + for ( + const nlohmann::json& item + : json_booleans + ) { + common::optional< + std::shared_ptr + > deserialized; + + std::tie( + deserialized, + error + ) = DeserializeBool( + item, + additional_properties + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_booleans + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"booleans" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_booleans->emplace_back( + std::move(*deserialized) + ); + + ++index_booleans; + } + + // endregion De-serialize booleans + + // region De-serialize classes + + const nlohmann::json& json_classes( + json["classes"] + ); + if (!json_classes.is_array()) { + error = common::make_optional( + common::Concat( + L"Expected an array, but got: ", + common::Utf8ToWstring( + json_classes.type_name() + ) + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"classes" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_classes = common::make_optional< + std::vector< + std::shared_ptr + > + >(); + + the_classes->reserve(json_classes.size()); + + size_t index_classes = 0; + + for ( + const nlohmann::json& item + : json_classes + ) { + common::optional< + std::shared_ptr + > deserialized; + + std::tie( + deserialized, + error + ) = DeserializeMyClass( + item, + additional_properties + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_classes + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + L"classes" + ) + ); + + return std::make_pair< + common::optional >, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + the_classes->emplace_back( + std::move(*deserialized) + ); + + ++index_classes; + } + + // endregion De-serialize classes + + return std::make_pair( + common::make_optional< + std::shared_ptr + >( + // NOTE (mristin): + // We deliberately do not use std::make_shared here to avoid an unnecessary + // upcast. + new types::ListOfPrimitives( + std::move(*the_strings), + std::move(*the_integers), + std::move(*the_booleans), + std::move(*the_classes) + ) + ), + common::nullopt + ); +} + +common::expected< + std::shared_ptr, + DeserializationError +> MyClassFrom( + const nlohmann::json& json, + bool additional_properties +) { + common::optional< + std::shared_ptr + > instance; + + common::optional error; + + std::tie( + instance, + error + ) = DeserializeMyClass( + json, + additional_properties + ); + + if (instance.has_value()) { + return std::move(*instance); + } + + if (!error.has_value()) { + throw std::logic_error( + "Unexpected null error when null instance." + ); + } + return common::make_unexpected( + std::move(*error) + ); +} + +common::expected< + std::shared_ptr, + DeserializationError +> ListOfPrimitivesFrom( + const nlohmann::json& json, + bool additional_properties +) { + common::optional< + std::shared_ptr + > instance; + + common::optional error; + + std::tie( + instance, + error + ) = DeserializeListOfPrimitives( + json, + additional_properties + ); + + if (instance.has_value()) { + return std::move(*instance); + } + + if (!error.has_value()) { + throw std::logic_error( + "Unexpected null error when null instance." + ); + } + return common::make_unexpected( + std::move(*error) + ); +} + +// endregion De-serialization + +// region Serialization + +/** + * \brief Represent a serialization error. + * + * We use this error internally to avoid unnecessary stack unwinding, + * but throw the \ref SerializationException at the final site of + * the serialization for the user. + */ +struct SerializationError { + /** + * Human-readable description of the error + */ + std::wstring cause; + + /** + * Path to the value that caused the error + */ + iteration::Path path; + + explicit SerializationError( + std::wstring a_cause + ) : cause(std::move(a_cause)) { + // Intentionally empty. + } +}; // struct SerializationError + +// region SerializationException + +std::string RenderSerializationErrorMessage( + const std::wstring& cause, + const iteration::Path& path +) { + return common::WstringToUtf8( + common::Concat( + L"Serialization failed at ", + path.ToWstring(), + L": ", + cause + ) + ); +} + +SerializationException::SerializationException( + std::wstring cause, + iteration::Path path +) : + cause_(std::move(cause)), + path_(std::move(path)), + msg_(RenderSerializationErrorMessage(cause, path)) { + // Intentionally empty. +} + +const char* SerializationException::what() const noexcept { + return msg_.c_str(); +} + +const std::wstring& SerializationException::cause() const noexcept { + return cause_; +} + +const iteration::Path& SerializationException::path() const noexcept { + return path_; +} + +// endregion SerializationException + +/** + * \brief Serialize the given number to a JSON value. + * + * We verify that the integer is within the range representable by 64-bit floats + * for interoperability with other de-serializers. + */ +std::pair< + common::optional, + common::optional +> SerializeInt64(int64_t value) { + if ( + value < -9007199254740991L + || value > 9007199254740991L + ) { + const std::wstring message = common::Concat( + L"The integer ", + std::to_wstring(value), + L" can not be serialized to JSON " + L"as it is outside the range [-2^53 + 1, 2^53 - 1] and can not " + L"be exactly represented as a 64-bit floating point number." + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + message + ) + ); + } + + return std::make_pair< + common::optional, + common::optional + >( + common::make_optional(value), + common::nullopt + ); +} + +/** + * Serialize the given text to a JSON value. + */ +nlohmann::json SerializeWstring( + const std::wstring& text +) { + return nlohmann::json( + common::WstringToUtf8(text) + ); +} + +/** + * Serialize the given bytes to a JSON value. + */ +nlohmann::json SerializeByteArray( + const std::vector& bytes +) { + return nlohmann::json( + std::move( + stringification::Base64Encode(bytes) + ) + ); +} + +std::pair< + common::optional, + common::optional +> SerializeIClass( + const types::IClass& that +); + +std::pair< + common::optional, + common::optional +> SerializeMyClass( + const types::IMyClass& that +) { + nlohmann::json result = nlohmann::json::object(); + + return std::make_pair< + common::optional, + common::optional + >( + common::make_optional(std::move(result)), + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> SerializeListOfPrimitives( + const types::IListOfPrimitives& that +) { + nlohmann::json result = nlohmann::json::object(); + + common::optional error; + + nlohmann::json json_strings = nlohmann::json::array(); + json_strings.get_ptr()->reserve( + that.strings().size() + ); + size_t index_strings = 0; + for ( + const std::wstring& item + : that.strings() + ) { + common::optional json_item; + std::tie( + json_item, + error + ) = SerializeIClass(*item); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_strings + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kStrings + ) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + json_strings.emplace_back( + std::move(*json_item) + ); + + ++index_strings; + } + result["strings"] = std::move( + json_strings + ); + + nlohmann::json json_integers = nlohmann::json::array(); + json_integers.get_ptr()->reserve( + that.integers().size() + ); + size_t index_integers = 0; + for ( + int64_t item + : that.integers() + ) { + common::optional json_item; + std::tie( + json_item, + error + ) = SerializeIClass(*item); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_integers + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kIntegers + ) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + json_integers.emplace_back( + std::move(*json_item) + ); + + ++index_integers; + } + result["integers"] = std::move( + json_integers + ); + + nlohmann::json json_booleans = nlohmann::json::array(); + json_booleans.get_ptr()->reserve( + that.booleans().size() + ); + size_t index_booleans = 0; + for ( + bool item + : that.booleans() + ) { + common::optional json_item; + std::tie( + json_item, + error + ) = SerializeIClass(*item); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_booleans + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kBooleans + ) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + json_booleans.emplace_back( + std::move(*json_item) + ); + + ++index_booleans; + } + result["booleans"] = std::move( + json_booleans + ); + + nlohmann::json json_classes = nlohmann::json::array(); + json_classes.get_ptr()->reserve( + that.classes().size() + ); + size_t index_classes = 0; + for ( + const std::shared_ptr& item + : that.classes() + ) { + common::optional json_item; + std::tie( + json_item, + error + ) = SerializeIClass(*item); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + index_classes + ) + ); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kClasses + ) + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + std::move(error) + ); + } + + json_classes.emplace_back( + std::move(*json_item) + ); + + ++index_classes; + } + result["classes"] = std::move( + json_classes + ); + + return std::make_pair< + common::optional, + common::optional + >( + common::make_optional(std::move(result)), + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> SerializeIClass( + const types::IClass& that +) { + switch (that.model_type()) { + case types::ModelType::kMyClass: + return SerializeMyClass( + dynamic_cast(that) + ); + case types::ModelType::kListOfPrimitives: + return SerializeListOfPrimitives( + dynamic_cast(that) + ); + default: { + std::string message = common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast( + that.model_type() + ) + ) + ); + + throw std::invalid_argument(message); + } + }; +} + +nlohmann::json Serialize( + const types::IClass& that +) { + common::optional result; + common::optional error; + + std::tie( + result, + error + ) = SerializeIClass(that); + + if (error.has_value()) { + throw SerializationException( + std::move(error->cause), + std::move(error->path) + ); + } + + return std::move(*result); +} + +// endregion Serialization + +} // namespace jsonization +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.hpp new file mode 100644 index 000000000..c989712f0 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/jsonization.hpp @@ -0,0 +1,202 @@ +#ifndef AAS_CORE_AAS_3_0_JSONIZATION_GUARD_ +#define AAS_CORE_AAS_3_0_JSONIZATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/iteration.hpp" +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include + +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup jsonization De/serialize instances from and to JSON. + * @{ + */ +namespace jsonization { + +/** + * Represent a segment of a JSON path to some value. + */ +class ISegment { + public: + /** + * \brief Convert the segment to a string in a JSON path. + */ + virtual std::wstring ToWstring() const = 0; + + virtual std::unique_ptr Clone() const = 0; + + virtual ~ISegment() = default; +}; // class ISegment + +/** + * Represent a property access on a JSON path. + */ +struct PropertySegment : public ISegment { + /** + * Name of the property in a JSON object + */ + std::wstring name; + + PropertySegment( + std::wstring a_name + ); + + std::wstring ToWstring() const override; + + std::unique_ptr Clone() const override; + + ~PropertySegment() override = default; +}; // struct PropertySegment + +/** + * Represent an index access on a JSON path. + */ +struct IndexSegment : public ISegment { + /** + * Index of the value in an array. + */ + size_t index; + + explicit IndexSegment( + size_t an_index + ); + + std::wstring ToWstring() const override; + + std::unique_ptr Clone() const override; + + ~IndexSegment() override = default; +}; // struct IndexSegment + +/** + * Represent a JSON path to some value. + */ +struct Path { + std::deque > segments; + + Path(); + Path(const Path& other); + Path(Path&& other); + Path& operator=(const Path& other); + Path& operator=(Path&& other); + + std::wstring ToWstring() const; +}; // struct Path + +// region De-serialization + +/** + * Represent a de-serialization error. + */ +struct DeserializationError { + /** + * Human-readable description of the error + */ + std::wstring cause; + + /** + * Path to the erroneous value + */ + Path path; + + explicit DeserializationError(std::wstring a_cause); + DeserializationError(std::wstring a_cause, Path a_path); +}; // struct DeserializationError + +/** + * \brief Deserialize \p json value to an instance + * of types::IMyClass. + * + * \param json value to be de-serialized + * \param additional_properties if not set, check that \p json contains + * no additional properties + * \return The deserialized instance, or a de-serialization error, if any. + */ +common::expected< + std::shared_ptr, + DeserializationError +> MyClassFrom( + const nlohmann::json& json, + bool additional_properties = false +); + +/** + * \brief Deserialize \p json value to an instance + * of types::IListOfPrimitives. + * + * \param json value to be de-serialized + * \param additional_properties if not set, check that \p json contains + * no additional properties + * \return The deserialized instance, or a de-serialization error, if any. + */ +common::expected< + std::shared_ptr, + DeserializationError +> ListOfPrimitivesFrom( + const nlohmann::json& json, + bool additional_properties = false +); + +// endregion Deserialization + +// region Serialization + +/** + * Represent an error in the serialization of an instance to JSON. + */ +class SerializationException : public std::exception { + public: + SerializationException( + std::wstring cause, + iteration::Path path + ); + + const char* what() const noexcept override; + + const std::wstring& cause() const noexcept; + const iteration::Path& path() const noexcept; + + ~SerializationException() noexcept override = default; + + private: + const std::wstring cause_; + const iteration::Path path_; + const std::string msg_; +}; // class SerializationException + +/** + * \brief Serialize \p that instance to a JSON value. + * + * \param that instance to be serialized + * \return The corresponding JSON value + * \throw \ref SerializationException if a value within \p that instance + * could not be serialized + */ +nlohmann::json Serialize( + const types::IClass& that +); + +// endregion Serialization + +} // namespace jsonization +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_JSONIZATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/pattern.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/pattern.cpp new file mode 100644 index 000000000..5839a702d --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/pattern.cpp @@ -0,0 +1,16 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/pattern.hpp" +#include "aas_core/aas_3_0/revm.hpp" + +namespace aas_core { +namespace aas_3_0 { +namespace pattern { + +} // namespace pattern +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/pattern.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/pattern.hpp new file mode 100644 index 000000000..e3739e47e --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/pattern.hpp @@ -0,0 +1,36 @@ +#ifndef AAS_CORE_AAS_3_0_PATTERN_GUARD_ +#define AAS_CORE_AAS_3_0_PATTERN_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/revm.hpp" + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup pattern Provide patterns to be matched using a multi-threaded virtual machine. + * + * The instructions should be supplied to aas_core::aas_3_0::revm::Match. While + * we could have theoretically included this code in verification, we decided to keep + * it separate for readability. You are not expected to use this module directly. + * @{ + */ +namespace pattern { + +} // namespace pattern +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_PATTERN_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/revm.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/revm.cpp new file mode 100644 index 000000000..a90d9d391 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/revm.cpp @@ -0,0 +1,863 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/revm.hpp" + +#pragma warning(push, 0) +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { +namespace revm { + +/** + * Represent the character such that it can be printed in the console. + * + * To that end, we escape the character if it is out of the printable ASCII set. + * + * This function is mostly meant for debugging purposes. + */ +std::string RepresentWCharacter(wchar_t character) { + switch (character) { + case L'\\':return "\\\\"; + case L'"':return "\\\""; + case L'\'':return "\\'"; + case L'\t':return "\\t"; + case L'\n':return "\\n"; + case L'\r':return "\\r"; + default: break; + } + + if (26 <= character && character <= 126) { + return std::string(1, static_cast(character)); + } + + static const char* digits = "0123456789ABCDEF"; + size_t digit_count = sizeof(wchar_t) * 2; + + std::string result; + result.resize(digit_count + 2); + result[0] = L'\\'; + result[1] = L'u'; + + for (size_t i = 0, j = (digit_count - 1) * 4; i < digit_count; ++i, j -= 4) { + const size_t digit_i = (character >> j) & 0x0f; + result[i + 2] = digits[digit_i]; + } + + return result; +} + +/** + * Represent the wide string for debugging purposes where it is printed to the console. + * + * To that end, we escape the individual characters if they are out of printable ASCII + * set. + */ +std::string RepresentWString(const std::wstring& text) { + std::vector parts; + parts.reserve(text.size()); + for (const wchar_t character : text) { + parts.emplace_back(RepresentWCharacter(character)); + } + + size_t size = 0; + for (const std::string& part : parts) { + size += part.size(); + } + + std::string result; + result.reserve(size); + for (const std::string& part : parts) { + result.append(part); + } + return result; +} + +InstructionChar::InstructionChar( + wchar_t a_character +) : + character(a_character) { + // Intentionally empty. +} + +InstructionKind InstructionChar::kind() const { + return InstructionKind::Char; +} + +std::string to_string(const InstructionChar& instruction) { + return common::Concat( + "char '", + RepresentWCharacter(instruction.character), + "'" + ); +} + +Range::Range( + wchar_t a_first, + wchar_t a_last +) : + first(a_first), + last(a_last) { + // NOTE (mristin): + // We are aware that exceptions in constructors should be avoided to prevent + // bug related to uninitialized object state. However, in this case, we do not + // see any risk for such a mistake. + if (a_first > a_last) { + throw std::invalid_argument( + common::Concat( + "The first character in a character range, ", + RepresentWCharacter(a_first), + ", is larger than the last character in the range, ", + RepresentWCharacter(a_last) + ) + ); + } +} + +std::string to_string(const Range& range) { + if (range.first == range.last) { + return RepresentWCharacter(range.first); + } + + return common::Concat( + RepresentWCharacter(range.first), + "-", + RepresentWCharacter(range.last) + ); +} + +InstructionSet::InstructionSet( + std::vector a_ranges +) : + ranges(std::move(a_ranges)) { + // NOTE (mristin): + // We are aware that exceptions in constructors should be avoided to prevent + // bug related to uninitialized object state. However, in this case, we do not + // see any risk for such a mistake. + if (ranges.empty()) { + throw std::invalid_argument( + "Unexpected NotSet instruction with empty ranges" + ); + } + + for (size_t i = 1; i < ranges.size(); ++i) { + if (ranges[i - 1].last >= ranges[i].first) { + throw std::invalid_argument( + common::Concat( + "The ranges for an InstructionSet are unexpectedly either " + "not sorted or overlapping. The range at index ", + std::to_string(i - 1), + " is ", + to_string(ranges[i - 1]), + " and the range at index ", + std::to_string(i), + " is ", + to_string(ranges[i]) + ) + ); + } + } +} + +InstructionKind InstructionSet::kind() const { + return InstructionKind::Set; +} + +std::string to_string(const InstructionSet& instruction) { + std::stringstream ss; + ss << "set '"; + + for (const auto& range : instruction.ranges) { + ss << to_string(range); + } + + ss << "'"; + return ss.str(); +} + +InstructionNotSet::InstructionNotSet( + std::vector a_ranges +) : + ranges(std::move(a_ranges)) { + // NOTE (mristin): + // We are aware that exceptions in constructors should be avoided to prevent + // bug related to uninitialized object state. However, in this case, we do not + // see any risk for such a mistake. + if (ranges.empty()) { + throw std::invalid_argument( + "Unexpected NotSet instruction with empty ranges" + ); + } + + for (size_t i = 1; i < ranges.size(); ++i) { + if (ranges[i - 1].last >= ranges[i].first) { + throw std::invalid_argument( + common::Concat( + "The ranges for an InstructionNotSet are unexpectedly either " + "not sorted or overlapping. The range at index ", + std::to_string(i - 1), + " is ", + to_string(ranges[i - 1]), + " and the range at index ", + std::to_string(i), + " is ", + to_string(ranges[i]) + ) + ); + } + } +} + +InstructionKind InstructionNotSet::kind() const { + return InstructionKind::NotSet; +} + +std::string to_string(const InstructionNotSet& instruction) { + std::stringstream ss; + ss << "not-set '"; + + for (const auto& range : instruction.ranges) { + ss << to_string(range); + } + + ss << "'"; + return ss.str(); +} + +InstructionKind InstructionAny::kind() const { + return InstructionKind::Any; +} + +std::string to_string(const InstructionAny&) { + return "any"; +} + +InstructionKind InstructionMatch::kind() const { + return InstructionKind::Match; +} + +std::string to_string(const InstructionMatch&) { + return "match"; +} + +InstructionJump::InstructionJump( + size_t a_target +) : + target(a_target) { + // Intentionally empty. +} + +InstructionKind InstructionJump::kind() const { + return InstructionKind::Jump; +} + +std::string to_string(const InstructionJump& instruction) { + return common::Concat( + "jump ", + std::to_string(instruction.target) + ); +} + +InstructionSplit::InstructionSplit( + size_t a_first_target, + size_t a_second_target +) : + first_target(a_first_target), + second_target(a_second_target) { + // Intentionally empty. +} + +InstructionKind InstructionSplit::kind() const { + return InstructionKind::Split; +} + +std::string to_string(const InstructionSplit& instruction) { + return common::Concat( + "split ", + std::to_string(instruction.first_target), + ", ", + std::to_string(instruction.second_target) + ); +} + +InstructionKind InstructionEnd::kind() const { + return InstructionKind::End; +} + +std::string to_string(const InstructionEnd&) { + return "end"; +} + +std::string to_string(const Instruction& instruction) { + switch (instruction.kind()) { + case InstructionKind::Char: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionChar& + >(instruction) + ); + + case InstructionKind::Set: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionSet& + >(instruction) + ); + + case InstructionKind::NotSet: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionNotSet& + >(instruction) + ); + + case InstructionKind::Any: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionAny& + >(instruction) + ); + + case InstructionKind::Match: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionMatch& + >(instruction) + ); + + case InstructionKind::Jump: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionJump& + >(instruction) + ); + + case InstructionKind::Split: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionSplit& + >(instruction) + ); + + case InstructionKind::End: + return to_string( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionEnd& + >(instruction) + ); + + default: + throw std::logic_error( + common::Concat( + "Unhandled instruction kind: ", + std::to_string( + static_cast(instruction.kind()) + ) + ) + ); + } +} + +std::string to_string( + const std::vector >& instructions +) { + std::stringstream ss; + for (size_t i = 0; i < instructions.size(); ++i) { + ss + << std::setw(4) << i << ": " + << to_string(*instructions[i]) << std::endl; + } + + return ss.str(); +} + +bool CharacterInRanges( + const std::vector& ranges, + wchar_t character +) { + if (ranges.empty()) { + return false; + } + + if (ranges.size() == 1) { + return (ranges[0].first <= character && character <= ranges[0].last); + } + + // Binary search + size_t begin = 0; + size_t end = ranges.size(); + + while (true) { + if (begin == end) { + return false; + } + + // NOTE (mristin): + // Most implementations of the binary search are buggy, see: + // https://en.wikipedia.org/wiki/Binary_search_algorithm#Implementation_issues. + // + // We try to avert some of the bugs by explicitly handling the case where there + // are at most 3 elements in the segment, so we stop here instead of proceeding + // recursively. + if (end - begin <= 3) { + for (size_t i = begin; i < end; ++i) { + const Range& range = ranges[i]; + if (range.first <= character && character <= range.last) { + return true; + } + } + return false; + } + + const size_t middle = (begin + end) / 2; + const Range& range = ranges[middle]; + if (character < range.first) { + end = middle; + } else if (character > range.last) { + begin = middle; + } else { + return true; + } + } +} + +/** + * Keep track of the threads currently being executed. + */ +class ThreadList { + public: + explicit ThreadList(size_t program_size) { + has_.resize(program_size, false); + items_.reserve(program_size); + } + + /** + * Add a new thread for the given program counter if it is not already in the list. + */ + void Spawn(size_t program_counter) { + #ifdef DEBUG + if (program_counter >= program_size_) { + throw std::invalid_argument( + common::Concat( + "Unexpected spawning of a thread at the program counter ", + std::to_string(program_counter), + " since the program size was indicated to be ", + std::to_string(program_size_) + ) + ); + } + #endif + + if (has_[program_counter]) { + return; + } + + has_[program_counter] = true; + items_.push_back(program_counter); + } + + bool Empty() const { + return items_.empty(); + } + + /** + * Pop the thread from the back, returning its program counter. + * + * The order of the threads is not guaranteed. + */ + size_t Pop() { + #ifdef DEBUG + if (items_.empty()) { + throw std::logic_error( + "You tried to pop from an empty thread list." + ); + } + #endif + + const size_t program_counter = items_.back(); + items_.pop_back(); + has_[program_counter] = false; + return program_counter; + } + + /** + * Clear the thread list, keeping its memory capacity. + */ + void Clear() { + std::fill(has_.begin(), has_.end(), false); + items_.clear(); + } + + /** + * Return the program counters corresponding to the spawned threads. + */ + const std::vector& Items() const { + return items_; + }; + + private: + /** + * Keep track of the program counters corresponding to the threads so that we can + * avoid the duplicate threads. + */ + std::vector has_; + + /** + * Keep track of the active threads. + */ + std::vector items_; +}; + +std::string to_string(const ThreadList& thread_list) { + if (thread_list.Empty()) { + return "[]"; + } + + std::vector items(thread_list.Items()); + std::sort(items.begin(), items.end()); + + std::stringstream ss; + ss << "["; + ss << std::to_string(items[0]); + + for (size_t i = 1; i < items.size(); ++i) { + ss << ", " << items[i]; + } + ss << "]"; + + return ss.str(); +} + +/** + * Try to match the program against the text. + * + * @return true if the text matches + */ +bool Match( + const std::vector >& program, + const std::wstring& text +) { + if (program.empty()) { + return false; + } + + // NOTE (mristin): + // We validate at the beginning so that we can avoid checks in + // the instruction loops. + for (size_t i = 0; i < program.size(); ++i) { + const Instruction& instruction = *program[i]; + + switch (instruction.kind()) { + case InstructionKind::Jump: { + const auto& instruction_jump( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionJump& + >( + instruction + ) + ); + + if (instruction_jump.target >= program.size()) { + throw std::invalid_argument( + common::Concat( + "Unexpected jump beyond the end of the program. Program has ", + std::to_string(program.size()), + " instruction(s), but the instruction ", + std::to_string(i), + " wants to jump to ", + std::to_string(instruction_jump.target) + ) + ); + } + break; + } + + case InstructionKind::Split: { + const auto& instruction_split( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionSplit& + >( + instruction + ) + ); + + if (instruction_split.first_target >= program.size()) { + throw std::invalid_argument( + common::Concat( + "Unexpected split & jump beyond the end of the program. Program has ", + std::to_string(program.size()), + " instruction(s), but the instruction ", + std::to_string(i), + " wants to split and make the first jump to ", + std::to_string(instruction_split.first_target) + ) + ); + } + + if (instruction_split.second_target >= program.size()) { + throw std::invalid_argument( + common::Concat( + "Unexpected split & jump beyond the end of the program. Program has ", + std::to_string(program.size()), + " instruction(s), but the instruction ", + std::to_string(i), + " wants to split and make the second jump to ", + std::to_string(instruction_split.second_target) + ) + ); + } + + break; + } + + default: + continue; + } + } + + // NOTE (mristin): + // See: https://swtch.com/~rsc/regexp/regexp2.html, + // Section "Thompson's Implementation". + + std::unique_ptr clist(std::make_unique(program.size())); + std::unique_ptr nlist(std::make_unique(program.size())); + + clist->Spawn(0); + + for (const wchar_t character : text) { + #ifdef DEBUG + if (!nlist->Empty()) { + throw std::logic_error( + "Expected the list of next-to-be-executed threads to be empty, " + "but it was not." + ); + } + #endif + + while (!clist->Empty()) { + const size_t program_counter = clist->Pop(); + + #ifdef DEBUG + if (program_counter >= program.size()) { + throw std::logic_error( + common::Concat( + "Unexpected program counter beyond the program. The program size was ", + std::to_string(program.size()), + ", while the program counter of a thread was ", + std::to_string(program_counter) + ) + ); + } + #endif + + const Instruction& instruction = *program[program_counter]; + + switch (instruction.kind()) { + case InstructionKind::Char: { + const auto& instruction_char( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionChar& + >(instruction) + ); + + if (character != instruction_char.character) { + // The matching failed for this thread. + break; + } + + nlist->Spawn(program_counter + 1); + break; + } + + case InstructionKind::Set: { + const auto& instruction_set( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionSet& + >(instruction) + ); + + if (!CharacterInRanges(instruction_set.ranges, character)) { + // The matching failed for this thread. + break; + } + + nlist->Spawn(program_counter + 1); + break; + } + + case InstructionKind::NotSet: { + const auto& instruction_not_set( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionNotSet& + >(instruction) + ); + + if (CharacterInRanges(instruction_not_set.ranges, character)) { + // The matching failed for this thread. + break; + } + + nlist->Spawn(program_counter + 1); + break; + } + + case InstructionKind::Any: { + // NOTE (mristin): + // We simply proceed to the next instruction at the next character without + // any checks. + nlist->Spawn(program_counter + 1); + break; + } + + case InstructionKind::Match: + return true; + + case InstructionKind::Jump: { + const auto& instruction_jump( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionJump& + >(instruction) + ); + + clist->Spawn(instruction_jump.target); + break; + } + + case InstructionKind::Split: { + const auto& instruction_split( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionSplit& + >(instruction) + ); + + clist->Spawn(instruction_split.first_target); + clist->Spawn(instruction_split.second_target); + break; + } + + case InstructionKind::End: { + // The matching failed for this thread as we have just consumed + // a character. + break; + } + + default: + throw std::logic_error( + common::Concat( + "Unhandled instruction kind: ", + std::to_string( + static_cast(instruction.kind()) + ) + ) + ); + } + } + + std::swap(clist, nlist); + nlist->Clear(); + } + + // NOTE (mristin): + // We need to process any pending jumps, splits and matches even tough there are + // no more characters to consume. + while (!clist->Empty()) { + const size_t program_counter = clist->Pop(); + + #ifdef DEBUG + if (program_counter >= program.size()) { + throw std::logic_error( + common::Concat( + "Unexpected program counter beyond the program. The program size was ", + std::to_string(program.size()), + ", while the program counter of a thread was ", + std::to_string(program_counter) + ) + ); + } + #endif + + const Instruction& instruction = *program[program_counter]; + + switch (instruction.kind()) { + case InstructionKind::Char: { // NOLINT(bugprone-branch-clone) + // We reached the end-of-input so there are no characters to be matched. + // This thread needs therefore to die. + break; + } + + case InstructionKind::Set: { + // We reached the end-of-input so there are no character sets to be matched. + // This thread needs therefore to die. + break; + } + + case InstructionKind::NotSet: { + // We reached the end-of-input so there are no character sets to be matched. + // This thread needs therefore to die. + break; + } + + case InstructionKind::Any: { + // We reached the end-of-input so there are no characters to be matched. + // This thread needs therefore to die. + break; + } + + case InstructionKind::Match: + return true; + + case InstructionKind::Jump: { + const auto& instruction_jump( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionJump& + >(instruction) + ); + + clist->Spawn(instruction_jump.target); + break; + } + + case InstructionKind::Split: { + const auto& instruction_split( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const InstructionSplit& + >(instruction) + ); + + clist->Spawn(instruction_split.first_target); + clist->Spawn(instruction_split.second_target); + break; + } + + case InstructionKind::End: { + // We reached the end-of-input so we match and move to the next instruction. + clist->Spawn(program_counter + 1); + break; + } + + default: + throw std::logic_error( + common::Concat( + "Unhandled instruction kind: ", + std::to_string( + static_cast(instruction.kind()) + ) + ) + ); + } + } + + return false; +} + +} // namespace revm +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/revm.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/revm.hpp new file mode 100644 index 000000000..fa54533ee --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/revm.hpp @@ -0,0 +1,215 @@ +#ifndef AAS_CORE_AAS_3_0_REVM_GUARD_ +#define AAS_CORE_AAS_3_0_REVM_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#pragma warning(push, 0) +#include +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup revm Match regular expressions using a multi-threaded virtual machine. + * + * The implementation in the standard library has exponential time complexity, so it was + * a major blocker for most of the practical inputs. For example, see this bug report: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93502 + * + * This implementation is based on Ken Thompson's approach which uses a virtual + * machine to match regular expressions. The original technique has been + * published in: + * Thompson, K., "Regular expression search algorithm", ACM 11(6) (June 1968) + * + * We followed a very clear and concise blog post which described in detail: + * https://swtch.com/~rsc/regexp/regexp2.html + * + * The ideas for additional instructions were taken from: + * https://www.codeproject.com/Articles/5256833/Regex-as-a-Tiny-Threaded-Virtual-Machine + * @{ + */ +namespace revm { + +enum class InstructionKind : std::uint8_t { + Char, + Set, + NotSet, + Any, + Match, + Jump, + Split, + End +}; + +/** + * Represent an instruction of the virtual machine. + */ +struct Instruction { + // NOTE (mristin): + // We avoid RTTI for performance reasons, and use our own enumerator instead. + virtual InstructionKind kind() const = 0; + + virtual ~Instruction() = default; +}; + +/** + * Match a single character. + * + * If the character on the String Pointer does not match the `character`, stop this + * thread as it failed. Otherwise, move the String Pointer to the next character, + * and the Program Counter to the next instruction. + */ +struct InstructionChar : Instruction { + wchar_t character; + + explicit InstructionChar(wchar_t a_character); + InstructionKind kind() const override; + ~InstructionChar() override = default; +}; + +std::string to_string(const InstructionChar& instruction); + +/** + * Define a character range. + */ +struct Range { + wchar_t first; + wchar_t last; + + Range(wchar_t a_first, wchar_t a_last); +}; + +std::string to_string(const Range& range); + +/** + * Check whether the character is in any of the given character ranges. + * + * @return true if the character is in any of the ranges + */ +bool CharacterInRanges( + const std::vector& ranges, + wchar_t character +); + +/** + * Match a set of characters. + * + * If the character on the String Pointer *is not* in the given set, stop this + * thread as it failed. Otherwise, move the String Pointer to the next character, + * and the Program Counter to the next instruction. + */ +struct InstructionSet : Instruction { + std::vector ranges; + + explicit InstructionSet(std::vector a_ranges); + InstructionKind kind() const override; + ~InstructionSet() override = default; +}; + +std::string to_string(const InstructionSet& instruction); + +/** + * Match an out-of-set character. + * + * If the character on the String Pointer *is* in the given set, stop this + * thread as it failed. Otherwise, move the String Pointer to the next character, + * and the Program Counter to the next instruction. + */ +struct InstructionNotSet : Instruction { + std::vector ranges; + + explicit InstructionNotSet(std::vector a_ranges); + InstructionKind kind() const override; + ~InstructionNotSet() override = default; +}; + +std::string to_string(const InstructionNotSet& instruction); + +/** + * Match any character. + */ +struct InstructionAny : Instruction { + InstructionKind kind() const override; + ~InstructionAny() override = default; +}; + +std::string to_string(const InstructionAny&); + +/** + * Stop this thread and signal that we found a match. + */ +struct InstructionMatch : Instruction { + InstructionKind kind() const override; + ~InstructionMatch() override = default; +}; + +std::string to_string(const InstructionMatch&); + +/** + * Jump to the indicated position in the program. + */ +struct InstructionJump : Instruction { + size_t target; + + explicit InstructionJump(size_t a_target); + InstructionKind kind() const override; + ~InstructionJump() override = default; +}; + +std::string to_string(const InstructionJump& instruction); + +/** + * Split the program in two threads, both jumping to different locations. The string + * pointer is kept as-is. + */ +struct InstructionSplit : Instruction { + size_t first_target; + size_t second_target; + + explicit InstructionSplit(size_t a_first_target, size_t a_second_target); + InstructionKind kind() const override; + ~InstructionSplit() override = default; +}; + +std::string to_string(const InstructionSplit& instruction); + +/** + * Match the end-of-input. + */ +struct InstructionEnd : Instruction { + InstructionKind kind() const override; + ~InstructionEnd() override = default; +}; + +std::string to_string(const InstructionEnd&); + +std::string to_string(const Instruction& instruction); + +std::string to_string( + const std::vector >& instructions +); + +/** + * Try to match the program against the text. + * @return true if the text matches + */ +bool Match( + const std::vector >& program, + const std::wstring& text +); + +} // namespace revm +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_REVM_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/stdout.txt b/test_data/cpp/test_main/list_of_primitives/expected_output/stdout.txt new file mode 100644 index 000000000..2d755fc5a --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/stdout.txt @@ -0,0 +1 @@ +Code generated to: diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/stringification.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/stringification.cpp new file mode 100644 index 000000000..53bb0d402 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/stringification.cpp @@ -0,0 +1,365 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/stringification.hpp" + +#pragma warning(push, 0) +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { +namespace stringification { + +const std::unordered_map< + std::string, + types::ModelType +> kModelTypeFromStringMap = { + { + "MyClass", + types::ModelType::kMyClass + }, + { + "ListOfPrimitives", + types::ModelType::kListOfPrimitives + } +}; + +common::optional ModelTypeFromString( + const std::string& text +) { + const auto it = kModelTypeFromStringMap.find( + text + ); + if (it == kModelTypeFromStringMap.end()) { + return {}; + } + return it->second; +} + +types::ModelType MustModelTypeFromString( + const std::string& text +) { + const auto it = kModelTypeFromStringMap.find( + text + ); + if (it == kModelTypeFromStringMap.end()) { + throw std::invalid_argument( + common::Concat( + "Unexpected ModelType literal: ", + text + ) + ); + } + return it->second; +} + +std::string to_string( + types::ModelType model_type +) { + switch (model_type) { + case types::ModelType::kMyClass: + return "MyClass"; + case types::ModelType::kListOfPrimitives: + return "ListOfPrimitives"; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast( + model_type + ) + ) + ) + ); + } +} + +// The following encoder has been adapted from Jouni Malinen to work with +// std::string. The original source code is available at: +// https://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.c +// +// See also the following StackOverflow question for a benchmark: +// https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c/41094722#41094722 + +constexpr std::size_t kCharBase64TableLen = 65; +static const unsigned char kCharBase64Table[kCharBase64TableLen]( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +); + +std::string Base64Encode( + const std::vector& bytes +) { + // See: https://cplusplus.com/reference/vector/vector/data/. + // The data is guaranteed to be a continuous block in memory. + const unsigned char* const src( + bytes.data() + ); + + const std::size_t len = bytes.size(); + + // 3-byte blocks to 4-byte + const std::size_t olen = 4 * ((len + 2) / 3); + + // Integer overflow? + if (olen < len) { + throw std::invalid_argument( + common::Concat( + "The calculation of the output length overflowed. " + "The length was: ", + std::to_string(len), + ", but the output length was calculated as: ", + std::to_string(olen) + ) + ); + } + + std::string out_string; + out_string.resize(olen); + + unsigned char* out( + reinterpret_cast( + &out_string[0] + ) + ); + + const unsigned char* const end = src + len; + + const unsigned char* in = src; + unsigned char* pos = out; + + while (end - in >= 3) { + *pos++ = kCharBase64Table[in[0] >> 2]; + *pos++ = kCharBase64Table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *pos++ = kCharBase64Table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; + *pos++ = kCharBase64Table[in[2] & 0x3f]; + in += 3; + } + + if (end - in) { + *pos++ = kCharBase64Table[in[0] >> 2]; + + if (end - in == 1) { + *pos++ = kCharBase64Table[(in[0] & 0x03) << 4]; + *pos++ = '='; + } else { + *pos++ = kCharBase64Table[ + ((in[0] & 0x03) << 4) | (in[1] >> 4) + ]; + *pos++ = kCharBase64Table[(in[1] & 0x0f) << 2]; + } + *pos++ = '='; + } + + return out_string; +} + +// The following decoder is vaguely based on: +// https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js, +// https://github.com/niklasvh/base64-arraybuffer/blob/master/src/index.ts and +// https://github.com/beatgammit/base64-js/blob/master/index.js. + +std::vector ConstructBase64Lookup() { + std::vector lookup(256, 255); + for (std::uint8_t i = 0; i < kCharBase64TableLen; ++i) { + lookup.at(kCharBase64Table[i]) = i; + } + return lookup; +} +const std::vector kBase64Lookup = ConstructBase64Lookup(); + +common::expected< + std::vector, + std::string +> Base64Decode( + const std::string& text +) { + if (text.empty()) { + return std::vector(); + } + + const std::size_t len = text.size(); + std::size_t len_wo_pad = len; + + // NOTE (mristin): + // Some implementations forget the padding, so we try to be robust and check + // for the padding manually. + std::size_t bytes_length = (len * 3) / 4; + if (text[len - 1] == '=') { + bytes_length--; + len_wo_pad--; + + if (text[len - 2] == '=') { + bytes_length--; + len_wo_pad--; + } + } + + std::vector bytes(bytes_length); + + const std::size_t base64_lookup_len = kBase64Lookup.size(); + + std::size_t pointer = 0; + + for (std::size_t i = 0; i < len; i += 4) { + // NOTE (mristin): + // Admittedly, this is very verbose code, but we want to be efficient, so we + // opted for performance over readability here. + + const unsigned char code0 = text[i]; + if (code0 >= base64_lookup_len) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i), + ": ", + std::to_string(code0), + " (code: ", + std::to_string(static_cast(code0)), + ")" + ); + + return common::make_unexpected(message); + } + const std::uint8_t encoded0 = kBase64Lookup[code0]; + if (encoded0 == 255) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i), + ": ", + std::to_string(code0), + " (code: ", + std::to_string(static_cast(code0)), + ")" + ); + + return common::make_unexpected(message); + } + + const unsigned char code1 = text[i + 1]; + if (code1 >= base64_lookup_len) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i + 1), + ": ", + std::to_string(code1), + " (code: ", + std::to_string(static_cast(code1)), + ")" + ); + + return common::make_unexpected(message); + } + const std::uint8_t encoded1 = kBase64Lookup[code1]; + if (encoded1 == 255) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i + 1), + ": ", + std::to_string(code1), + " (code: ", + std::to_string(static_cast(code1)), + ")" + ); + + return common::make_unexpected(message); + } + + // We map padding to 65, which is the value of "A". + const unsigned char code2 = i + 2 < len_wo_pad ? text[i + 2] : 65; + if (code2 >= base64_lookup_len) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i + 2), + ": ", + std::to_string(code2), + " (code: ", + std::to_string(static_cast(code2)), + ")" + ); + + return common::make_unexpected(message); + } + const std::uint8_t encoded2 = kBase64Lookup[code2]; + if (encoded2 == 255) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i + 2), + ": ", + std::to_string(code2), + " (code: ", + std::to_string(static_cast(code2)), + ")" + ); + + return common::make_unexpected(message); + } + + // We map padding to 65, which is the value of 'A'. + const unsigned char code3 = i + 3 < len_wo_pad ? text[i + 3] : 65; + if (code3 >= base64_lookup_len) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i + 3), + ": ", + std::to_string(code3), + " (code: ", + std::to_string(static_cast(code3)), + ")" + ); + + return common::make_unexpected(message); + } + const std::uint8_t encoded3 = kBase64Lookup[code3]; + if (encoded3 == 255) { + std::string message = common::Concat( + "Expected a valid character from base64-encoded string, " + "but got at index ", + std::to_string(i + 3), + ": ", + std::to_string(code3), + " (code: ", + std::to_string(static_cast(code3)), + ")" + ); + + return common::make_unexpected(message); + } + + if (pointer >= bytes_length) { + break; + } + bytes[pointer] = (encoded0 << 2) | (encoded1 >> 4); + pointer++; + + if (pointer >= bytes_length) { + break; + } + bytes[pointer] = ((encoded1 & 15) << 4) | (encoded2 >> 2); + pointer++; + + if (pointer >= bytes_length) { + break; + } + bytes[pointer] = ((encoded2 & 3) << 6) | (encoded3 & 63); + pointer++; + } + + return bytes; +} + +} // namespace stringification +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/stringification.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/stringification.hpp new file mode 100644 index 000000000..ed4f86b19 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/stringification.hpp @@ -0,0 +1,93 @@ +#ifndef AAS_CORE_AAS_3_0_STRINGIFICATION_GUARD_ +#define AAS_CORE_AAS_3_0_STRINGIFICATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup stringification Translate to strings, and, where applicable, from strings. + * @{ + */ +namespace stringification { + +/** + * Try to parse the \p text as a model type literal. + * + * \param text to be parsed + * \return literal, or nothing, if \p text invalid + */ +common::optional ModelTypeFromString( + const std::string& text +); + +/** + * Parse the \p text as a model type literal. + * + * \param text to be parsed + * \return literal + * \throw std::invalid_argument if \p text invalid + */ +types::ModelType MustModelTypeFromString( + const std::string& text +); + +/** + * Translate the enumeration literal \p model_type to text. + * + * \param model_type to be converted into text + * \return text representation of \p model_type + * \throw std::invalid_argument if \p model_type invalid + */ +std::string to_string( + types::ModelType model_type +); + +/** + * Encode the \p bytes with base64 to a std::string. + * + * \param bytes to be encoded + * \return base64-encoding of \p bytes + */ +std::string Base64Encode( + const std::vector& bytes +); + +/** + * Decode the \p the text with base64 to bytes. + * + * \remark \parblock + * We intentionally decode from std::string and *not* from std::wstring as + * the de/serialization libraries currently work only with UTF-8 encoded strings. + * \endparblock + * + * \param text to be decoded + * \return decoded bytes, or error message, if any. + */ +common::expected< + std::vector, + std::string +> Base64Decode( + const std::string& text +); + +} // namespace stringification +} // namespace aas_3_0 +} // namespace aas_core + +/**@}*/ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_STRINGIFICATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/types.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/types.cpp new file mode 100644 index 000000000..e5428649f --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/types.cpp @@ -0,0 +1,158 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/types.hpp" + +namespace aas_core { +namespace aas_3_0 { +namespace types { + +// region MyClass + +MyClass::MyClass() { + // Intentionally empty. +} + +ModelType MyClass::model_type() const { + return ModelType::kMyClass; +} + +// endregion MyClass + +// region ListOfPrimitives + +ListOfPrimitives::ListOfPrimitives( + std::vector strings, + std::vector integers, + std::vector booleans, + std::vector< + std::shared_ptr + > classes +) { + strings_ = std::move(strings); + + integers_ = std::move(integers); + + booleans_ = std::move(booleans); + + classes_ = std::move(classes); +} + +ModelType ListOfPrimitives::model_type() const { + return ModelType::kListOfPrimitives; +} + +const std::vector& ListOfPrimitives::strings() const { + return strings_; +} + +std::vector& ListOfPrimitives::mutable_strings() { + return strings_; +} + +void ListOfPrimitives::set_strings( + std::vector value +) { + strings_ = value; +} + +const std::vector& ListOfPrimitives::integers() const { + return integers_; +} + +std::vector& ListOfPrimitives::mutable_integers() { + return integers_; +} + +void ListOfPrimitives::set_integers( + std::vector value +) { + integers_ = value; +} + +const std::vector& ListOfPrimitives::booleans() const { + return booleans_; +} + +std::vector& ListOfPrimitives::mutable_booleans() { + return booleans_; +} + +void ListOfPrimitives::set_booleans( + std::vector value +) { + booleans_ = value; +} + +const std::vector< + std::shared_ptr +>& ListOfPrimitives::classes() const { + return classes_; +} + +std::vector< + std::shared_ptr +>& ListOfPrimitives::mutable_classes() { + return classes_; +} + +void ListOfPrimitives::set_classes( + std::vector< + std::shared_ptr + > value +) { + classes_ = value; +} + +// endregion ListOfPrimitives + +// region Is-a functions + +bool IsMyClass( + const IClass& that +) { + switch (that.model_type()) { + case ModelType::kMyClass: + return true; + case ModelType::kListOfPrimitives: + return false; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast(that.model_type()) + ) + ) + ); + } +} + +bool IsListOfPrimitives( + const IClass& that +) { + switch (that.model_type()) { + case ModelType::kMyClass: + return false; + case ModelType::kListOfPrimitives: + return true; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast(that.model_type()) + ) + ) + ); + } +} + +// endregion Is-a functions + +} // namespace types +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/types.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/types.hpp new file mode 100644 index 000000000..1b66e3b48 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/types.hpp @@ -0,0 +1,253 @@ +#ifndef AAS_CORE_AAS_3_0_TYPES_GUARD_ +#define AAS_CORE_AAS_3_0_TYPES_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" + +#pragma warning(push, 0) +#include +#include +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup types Define data structures corresponding to the meta-model. + * @{ + */ +namespace types { + +// region Enumerations + +/** + * Enumerate the model types for faster type switches. + * + * For example, switch statements can be implemented as jump tables. + */ +enum class ModelType : std::uint32_t { + kMyClass = 0, + kListOfPrimitives = 1 +}; + +// endregion Enumerations + +// region Forward declaration of interfaces + +// endregion Forward declaration of interfaces + +class IMyClass; + +class IListOfPrimitives; + +// region Class interfaces + +/** + * Model the most general instance of the model. + */ +class IClass { + public: + /** + * Indicate the runtime model type. + */ + virtual ModelType model_type() const = 0; + virtual ~IClass() = default; +}; + +class IMyClass + : virtual public IClass { + public: + virtual ~IMyClass() = default; +}; + +class IListOfPrimitives + : virtual public IClass { + public: + virtual const std::vector& strings() const = 0; + + virtual std::vector& mutable_strings() = 0; + + virtual void set_strings( + std::vector value + ) = 0; + + virtual const std::vector& integers() const = 0; + + virtual std::vector& mutable_integers() = 0; + + virtual void set_integers( + std::vector value + ) = 0; + + virtual const std::vector& booleans() const = 0; + + virtual std::vector& mutable_booleans() = 0; + + virtual void set_booleans( + std::vector value + ) = 0; + + virtual const std::vector< + std::shared_ptr + >& classes() const = 0; + + virtual std::vector< + std::shared_ptr + >& mutable_classes() = 0; + + virtual void set_classes( + std::vector< + std::shared_ptr + > value + ) = 0; + + virtual ~IListOfPrimitives() = default; +}; + +// endregion + +// region Definitions of concrete classes + +class MyClass + : public IMyClass { + public: + MyClass() {} + + ModelType model_type() const override; + + ~MyClass() override = default; +}; + +class ListOfPrimitives + : public IListOfPrimitives { + public: + ListOfPrimitives( + std::vector strings, + std::vector integers, + std::vector booleans, + std::vector< + std::shared_ptr + > classes + ); + + ModelType model_type() const override; + + // region Get and set strings_ + + const std::vector& strings() const override; + + std::vector& mutable_strings() override; + + void set_strings( + std::vector value + ) override; + + // endregion + + // region Get and set integers_ + + const std::vector& integers() const override; + + std::vector& mutable_integers() override; + + void set_integers( + std::vector value + ) override; + + // endregion + + // region Get and set booleans_ + + const std::vector& booleans() const override; + + std::vector& mutable_booleans() override; + + void set_booleans( + std::vector value + ) override; + + // endregion + + // region Get and set classes_ + + const std::vector< + std::shared_ptr + >& classes() const override; + + std::vector< + std::shared_ptr + >& mutable_classes() override; + + void set_classes( + std::vector< + std::shared_ptr + > value + ) override; + + // endregion + + ~ListOfPrimitives() override = default; + + private: + std::vector strings_; + + std::vector integers_; + + std::vector booleans_; + + std::vector< + std::shared_ptr + > classes_; +}; + +// endregion + +// region Is-a functions + +/** + * \brief Check whether \p that instance is of runtime type + * \ref IMyClass. + * + * We use `IClass::model_type` to determine the runtime type, which is + * a bit faster than native C++'s RTTI. + * + * \param that instance to check for runtime type + * \return `true` if \p that instance is indeed + * an instance of \ref IMyClass + */ +bool IsMyClass( + const IClass& that +); + +/** + * \brief Check whether \p that instance is of runtime type + * \ref IListOfPrimitives. + * + * We use `IClass::model_type` to determine the runtime type, which is + * a bit faster than native C++'s RTTI. + * + * \param that instance to check for runtime type + * \return `true` if \p that instance is indeed + * an instance of \ref IListOfPrimitives + */ +bool IsListOfPrimitives( + const IClass& that +); + +// endregion Is-a functions + +} // namespace types +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_TYPES_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/verification.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/verification.cpp new file mode 100644 index 000000000..b2233917d --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/verification.cpp @@ -0,0 +1,727 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/constants.hpp" +#include "aas_core/aas_3_0/pattern.hpp" +#include "aas_core/aas_3_0/revm.hpp" +#include "aas_core/aas_3_0/verification.hpp" + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { +namespace verification { + +// region struct Error + +Error::Error( + std::wstring a_cause +) : + cause(std::move(a_cause)) { + // Intentionally empty. +} + +Error::Error( + std::wstring a_cause, + iteration::Path a_path +) : + cause(std::move(a_cause)), + path(std::move(a_path)) { + // Intentionally empty. +} + +// endregion struct Error + +// region class AlwaysDoneVerificator + +class AlwaysDoneVerificator : public impl::IVerificator { + public: + void Start() override; + void Next() override; + bool Done() const override; + const Error& Get() const override; + Error& GetMutable() override; + long Index() const override; + std::unique_ptr Clone() const override; + + virtual ~AlwaysDoneVerificator() = default; +}; // class AlwaysDoneVerificator + +void AlwaysDoneVerificator::Start() { + // Intentionally empty. +} + +void AlwaysDoneVerificator::Next() { + throw std::logic_error( + "You want to move an AlwaysDoneVerificator, " + "but the verificator is always done, as its name suggests." + ); +} + +bool AlwaysDoneVerificator::Done() const { + return true; +} + +const Error& AlwaysDoneVerificator::Get() const { + throw std::logic_error( + "You want to get from an AlwaysDoneVerificator, " + "but the verificator is always done, as its name suggests." + ); +} + +Error& AlwaysDoneVerificator::GetMutable() { + throw std::logic_error( + "You want to get mutable from an AlwaysDoneVerificator, " + "but the verificator is always done, as its name suggests." + ); +} + +long AlwaysDoneVerificator::Index() const { + return -1; +} + +std::unique_ptr AlwaysDoneVerificator::Clone() const { + return common::make_unique(*this); +} + +// endregion class AlwaysDoneVerificator + +/** + * Produce a non-recursive verificator of the instance given its runtime model type. + */ +std::unique_ptr NewNonRecursiveVerificator( + const std::shared_ptr& instance +); + +// region Non-recursive verificators + +namespace non_recursive_verificator { + +class OfMyClass : public impl::IVerificator { + public: + OfMyClass( + const std::shared_ptr& instance + ); + + void Start() override; + void Next() override; + bool Done() const override; + const Error& Get() const override; + Error& GetMutable() override; + long Index() const override; + + std::unique_ptr Clone() const override; + + ~OfMyClass() override = default; +}; // class OfMyClass + +OfMyClass::OfMyClass( + const std::shared_ptr& +) { + // Intentionally empty. +} + +void OfMyClass::Start() { + // Intentionally empty. +} + +void OfMyClass::Next() { + throw std::logic_error( + "You want to move " + "a verificator OfMyClass, " + "but the verificator is always done as " + "IMyClass " + "has no invariants defined." + ); +} + +bool OfMyClass::Done() const { + return true; +} + +const Error& OfMyClass::Get() const { + throw std::logic_error( + "You want to get from " + "a verificator OfMyClass, " + "but the verificator is always done as " + "IMyClass " + "has no invariants defined." + ); +} + +Error& OfMyClass::GetMutable() { + throw std::logic_error( + "You want to get mutable from " + "a verificator OfMyClass, " + "but the verificator is always done as " + "IMyClass " + "has no invariants defined." + ); +} + +long OfMyClass::Index() const { + return -1; +} + +std::unique_ptr OfMyClass::Clone() const { + return common::make_unique< + OfMyClass + >(*this); +} + +class OfListOfPrimitives : public impl::IVerificator { + public: + OfListOfPrimitives( + const std::shared_ptr& instance + ); + + void Start() override; + void Next() override; + bool Done() const override; + const Error& Get() const override; + Error& GetMutable() override; + long Index() const override; + + std::unique_ptr Clone() const override; + + ~OfListOfPrimitives() override = default; +}; // class OfListOfPrimitives + +OfListOfPrimitives::OfListOfPrimitives( + const std::shared_ptr& +) { + // Intentionally empty. +} + +void OfListOfPrimitives::Start() { + // Intentionally empty. +} + +void OfListOfPrimitives::Next() { + throw std::logic_error( + "You want to move " + "a verificator OfListOfPrimitives, " + "but the verificator is always done as " + "IListOfPrimitives " + "has no invariants defined." + ); +} + +bool OfListOfPrimitives::Done() const { + return true; +} + +const Error& OfListOfPrimitives::Get() const { + throw std::logic_error( + "You want to get from " + "a verificator OfListOfPrimitives, " + "but the verificator is always done as " + "IListOfPrimitives " + "has no invariants defined." + ); +} + +Error& OfListOfPrimitives::GetMutable() { + throw std::logic_error( + "You want to get mutable from " + "a verificator OfListOfPrimitives, " + "but the verificator is always done as " + "IListOfPrimitives " + "has no invariants defined." + ); +} + +long OfListOfPrimitives::Index() const { + return -1; +} + +std::unique_ptr OfListOfPrimitives::Clone() const { + return common::make_unique< + OfListOfPrimitives + >(*this); +} + +} // namespace non_recursive_verificator + +std::unique_ptr NewNonRecursiveVerificator( + const std::shared_ptr& instance +) { + switch (instance->model_type()) { + case types::ModelType::kMyClass: + return common::make_unique< + non_recursive_verificator::OfMyClass + >( + instance + ); + case types::ModelType::kListOfPrimitives: + return common::make_unique< + non_recursive_verificator::OfListOfPrimitives + >( + instance + ); + default: + throw std::logic_error( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast(instance->model_type()) + ) + ) + ); + } +} + +// endregion Non-recursive verificators + +// region Recursive verificators + +class RecursiveVerificator : public impl::IVerificator { + public: + RecursiveVerificator( + const std::shared_ptr& instance + ); + + RecursiveVerificator(const RecursiveVerificator& other); + RecursiveVerificator(RecursiveVerificator&& other); + RecursiveVerificator& operator=(const RecursiveVerificator& other); + RecursiveVerificator& operator=(RecursiveVerificator&& other); + + void Start() override; + void Next() override; + bool Done() const override; + const Error& Get() const override; + Error& GetMutable() override; + long Index() const override; + + std::unique_ptr Clone() const override; + + ~RecursiveVerificator() override = default; + + private: + // NOTE(mristin): + // We use a pointer to a shared pointer here so that we can implement + // copy-assignment and move-assignment. Otherwise, if we used a constant + // reference here, the assignments could not be implemented as C++ does not + // allow re-binding of constant references. + const std::shared_ptr* instance_; + + std::uint32_t state_; + std::unique_ptr verificator_; + bool done_; + long index_; + std::unique_ptr error_; + common::optional iterator_; + common::optional iterator_end_; + + void Execute(); +}; // class RecursiveVerificator + +RecursiveVerificator::RecursiveVerificator( + const std::shared_ptr& instance +) : instance_(&instance) { + // Intentionally empty. +} + +RecursiveVerificator::RecursiveVerificator(const RecursiveVerificator& other) { + instance_ = other.instance_; + state_ = other.state_; + verificator_ = other.verificator_->Clone(); + done_ = other.done_; + index_ = other.index_; + error_ = common::make_unique(*(other.error_)); + iterator_ = other.iterator_; + iterator_end_ = other.iterator_end_; +} + +RecursiveVerificator::RecursiveVerificator(RecursiveVerificator&& other) { + instance_ = other.instance_; + state_ = other.state_; + verificator_ = std::move(other.verificator_); + done_ = other.done_; + index_ = other.index_; + error_ = std::move(other.error_); + iterator_ = std::move(other.iterator_); + iterator_end_ = std::move(other.iterator_end_); +} + +RecursiveVerificator& RecursiveVerificator::operator=( + const RecursiveVerificator& other +) { + return *this = RecursiveVerificator(other); +} + +RecursiveVerificator& RecursiveVerificator::operator=(RecursiveVerificator&& other) { + if (this != &other) { + instance_ = other.instance_; + state_ = other.state_; + verificator_ = std::move(other.verificator_); + done_ = other.done_; + index_ = other.index_; + error_ = std::move(other.error_); + iterator_ = std::move(other.iterator_); + iterator_end_ = std::move(other.iterator_end_); + } + + return *this; +} + +void RecursiveVerificator::Start() { + state_ = 0; + Execute(); +} + +void RecursiveVerificator::Next() { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to get from a RecursiveVerificator, " + "but the verificator was done." + ); + } + #endif + + Execute(); +} + +bool RecursiveVerificator::Done() const { + return done_; +} + +const Error& RecursiveVerificator::Get() const { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to get from a RecursiveVerificator, " + "but the verificator is done." + ); + } + #endif + + return *error_; +} + +Error& RecursiveVerificator::GetMutable() { + #ifdef DEBUG + if (Done()) { + throw std::logic_error( + "You want to get mutable from a RecursiveVerificator, " + "but the verificator is done." + ); + } + #endif + + return *error_; +} + +long RecursiveVerificator::Index() const { + #ifdef DEBUG + if (Done() && index_ != -1) { + throw std::logic_error( + common::Concat( + "Expected index to be -1 " + "from a done RecursiveVerificator, " + "but got: ", + std::to_string(index_) + ) + ); + } + #endif + + return index_; +} + +std::unique_ptr RecursiveVerificator::Clone() const { + return common::make_unique(*this); +} + +void RecursiveVerificator::Execute() { + while (true) { + switch (state_) { + case 0: { + error_ = nullptr; + index_ = -1; + done_ = false; + + verificator_ = NewNonRecursiveVerificator(*instance_); + verificator_->Start(); + } + + case 1: { + if (!(!verificator_->Done())) { + state_ = 3; + continue; + } + + // We intentionally take over the ownership of the errors' data members, + // as we know the implementation in all the detail, and want to avoid a costly + // copy. + error_ = common::make_unique( + std::move( + verificator_->GetMutable() + ) + ); + // No path is prepended as the error refers to the instance itself. + ++index_; + + state_ = 2; + return; + } + + case 2: { + verificator_->Next(); + + state_ = 1; + continue; + } + + case 3: { + verificator_ = nullptr; + + { + // NOTE (mristin): + // We will not need descent, so we introduce it in the scope. + iteration::Descent descent( + *instance_ + ); + iterator_ = std::move(descent.begin()); + + // NOTE (mristin): + // descent.end() is a constant reference, so we make an explicit + // copy here. + iterator_end_ = descent.end(); + } + } + + case 4: { + if (!(*iterator_ != *iterator_end_)) { + state_ = 8; + continue; + } + + verificator_ = NewNonRecursiveVerificator( + *(*iterator_) + ); + verificator_->Start(); + } + + case 5: { + if (!(!verificator_->Done())) { + state_ = 7; + continue; + } + + // We intentionally take over the ownership of the errors' data members, + // as we know the implementation in all the detail, and want to avoid a costly + // copy. + error_ = common::make_unique( + std::move( + verificator_->GetMutable() + ) + ); + + error_->path = std::move( + iteration::MaterializePath( + *iterator_ + ) + ); + + ++index_; + + state_ = 6; + return; + } + + case 6: { + verificator_->Next(); + + state_ = 5; + continue; + } + + case 7: { + verificator_ = nullptr; + + ++(*iterator_); + + state_ = 4; + continue; + } + + case 8: { + iterator_.reset(); + iterator_end_.reset(); + done_ = true; + index_ = -1; + + // We invalidate the state since we reached the end of the routine. + state_ = 9; + return; + } + + default: + throw std::logic_error( + common::Concat( + "Invalid state_: ", + std::to_string(state_) + ) + ); + } + } +} + +// endregion Recursive verificators + +// region NonRecursiveVerification + +NonRecursiveVerification::NonRecursiveVerification( + const std::shared_ptr& instance +) : instance_(instance) { + // Intentionally empty. +} + +Iterator NonRecursiveVerification::begin() const { + std::unique_ptr verificator( + NewNonRecursiveVerificator(instance_) + ); + + verificator->Start(); + + // NOTE(mristin): + // We short-circuit here for efficiency, as we can immediately dispose + // of the verificator. + if (verificator->Done()) { + return Iterator(common::make_unique()); + } + + return Iterator(std::move(verificator)); +} + +const Iterator& NonRecursiveVerification::end() const { + static Iterator iterator(common::make_unique()); + return iterator; +} + +// endregion NonRecursiveVerification + +// region RecursiveVerification + +RecursiveVerification::RecursiveVerification( + const std::shared_ptr& instance +) : instance_(instance) { + // Intentionally empty. +} + +Iterator RecursiveVerification::begin() const { + std::unique_ptr verificator( + common::make_unique(instance_) + ); + + verificator->Start(); + + // NOTE(mristin): + // We short-circuit here for efficiency, as we can immediately dispose + // of the verificator. + if (verificator->Done()) { + return Iterator(common::make_unique()); + } + + return Iterator(std::move(verificator)); +} + +const Iterator& RecursiveVerification::end() const { + static Iterator iterator(common::make_unique()); + return iterator; +} + +// endregion RecursiveVerification + +// region struct Iterator + +Iterator::Iterator( + const Iterator& other +) : + verificator_(other.verificator_->Clone()) { + // Intentionally empty. +} + +Iterator::Iterator( + Iterator&& other +) : + verificator_(std::move(other.verificator_)) { + // Intentionally empty. +} + +Iterator& Iterator::operator=(const Iterator& other) { + return *this = Iterator(other); +} + +Iterator& Iterator::operator=(Iterator&& other) { + if (this != &other) { + verificator_ = std::move(other.verificator_); + } + + return *this; +} + +const Error& Iterator::operator*() const { + if (verificator_->Done()) { + throw std::logic_error( + "You want to de-reference from a completed iterator " + "over verification errors." + ); + } + + return verificator_->Get(); +} + +const Error* Iterator::operator->() const { + if (verificator_->Done()) { + throw std::logic_error( + "You want to de-reference from a completed iterator " + "over verification errors." + ); + } + + return &(verificator_->Get()); +} + +// Prefix increment +Iterator& Iterator::operator++() { + if (verificator_->Done()) { + throw std::logic_error( + "You want to move a completed iterator " + "over verification errors." + ); + } + + verificator_->Next(); + return *this; +} + +// Postfix increment +Iterator Iterator::operator++(int) { + Iterator result(*this); + ++(*this); + return result; +} + +bool operator==(const Iterator& a, const Iterator& b) { + return a.verificator_->Index() == b.verificator_->Index(); +} + +bool operator!=(const Iterator& a, const Iterator& b) { + return a.verificator_->Index() != b.verificator_->Index(); +} + +// endregion struct Iterator + +} // namespace verification +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/verification.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/verification.hpp new file mode 100644 index 000000000..1e51a3abf --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/verification.hpp @@ -0,0 +1,225 @@ +#ifndef AAS_CORE_AAS_3_0_VERIFICATION_GUARD_ +#define AAS_CORE_AAS_3_0_VERIFICATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/iteration.hpp" +#include "aas_core/aas_3_0/pattern.hpp" +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup verification Verify that instances conform to the meta-model constraints. + * @{ + */ +namespace verification { + +// region Forward declarations +class Iterator; +class IVerification; + +namespace impl { +class IVerificator; +} // namespace impl +// endregion Forward declarations + +/** + * Represent a verification error in an instance. + */ +struct Error { + /** + * Human-readable description of the error + */ + std::wstring cause; + + /** + * Path to the erroneous value + */ + iteration::Path path; + + explicit Error(std::wstring a_cause); + Error(std::wstring a_cause, iteration::Path a_path); +}; // struct Error + +/** + * \brief Iterate over the verification errors. + * + * The user is expected to take ownership of the errors if they need to be further + * processed. + * + * Unlike STL, this is not a light-weight iterator. We implement + * a "yielding" iterator by leveraging code generation so that we always keep + * the model stack as well as the properties verified thus far. + * + * This means that copy-construction and equality comparisons are much more heavy-weight + * than you'd usually expect from an STL iterator. For example, if you want to sort + * the errors by some criterion, you are most probably faster if you populate a vector, + * and then sort the vector. + * + * Also, given that this iterator is not light-weight, you should in almost all cases + * avoid the postfix increment (it++) and prefer the prefix one (++it) as the postfix + * increment would create an iterator copy every time. + * + * We follow the C++ standard, and assume that comparison between the two iterators + * over two different collections results in undefined behavior. See + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html and + * https://stackoverflow.com/questions/4657513/comparing-iterators-from-different-containers. + */ +class Iterator { + using iterator_category = std::forward_iterator_tag; + /// The difference is meaningless, but has to be defined. + using difference_type = std::ptrdiff_t; + using value_type = Error; + using pointer = const Error*; + using reference = const Error&; + + public: + explicit Iterator( + std::unique_ptr verificator + ) : + verificator_(std::move(verificator)) { + // Intentionally empty. + } + + Iterator(const Iterator& other); + Iterator(Iterator&& other); + + Iterator& operator=(const Iterator& other); + Iterator& operator=(Iterator&& other); + + reference operator*() const; + pointer operator->() const; + + // Prefix increment + Iterator& operator++(); + + // Postfix increment + Iterator operator++(int); + + friend bool operator==(const Iterator& a, const Iterator& b); + friend bool operator!=(const Iterator& a, const Iterator& b); + + private: + std::unique_ptr verificator_; +}; + +bool operator==(const Iterator& a, const Iterator& b); + +bool operator!=(const Iterator& a, const Iterator& b); + +/// \cond HIDDEN +namespace impl { +class IVerificator { + public: + virtual void Start() = 0; + virtual void Next() = 0; + virtual bool Done() const = 0; + + virtual const Error& Get() const = 0; + virtual Error& GetMutable() = 0; + virtual long Index() const = 0; + + virtual std::unique_ptr Clone() const = 0; + + virtual ~IVerificator() = default; +}; // class IVerificator +} // namespace impl +/// \endcond + +class IVerification { + public: + virtual Iterator begin() const = 0; + virtual const Iterator& end() const = 0; + virtual ~IVerification() = default; +}; // class IVerification + +/** + * \brief Verify that the instance conforms to the meta-model constraints. + * + * Do not proceed to verify the instances referenced from + * the given instance. + * + * Range-based loops should fit the vast majority of the use cases: + * \code + * std::shared_ptr env = ...; + * for (const Error& error : NonRecursiveVerification(env)) { + * report_somehow(error); + * } + * \endcode + * + * We use const references to shared pointers here for efficiency. Since + * we do not make a copy of \p that shared pointer, it is very important that + * the given shared pointer outlives the verification, lest cause undefined behavior. + * See these StackOverflow questions: + * * https://stackoverflow.com/questions/12002480/passing-stdshared-ptr-to-constructors/12002668#12002668 + * * https://stackoverflow.com/questions/3310737/should-we-pass-a-shared-ptr-by-reference-or-by-value + * * https://stackoverflow.com/questions/37610494/passing-const-shared-ptrt-versus-just-shared-ptrt-as-parameter + */ +class NonRecursiveVerification : public IVerification { + public: + NonRecursiveVerification( + const std::shared_ptr& instance + ); + + Iterator begin() const override; + const Iterator& end() const override; + + ~NonRecursiveVerification() override = default; + private: + const std::shared_ptr& instance_; +}; // class NonRecursiveVerification + +/** + * \brief Verify that the instance conforms to the meta-model constraints. + * + * Also verify recursively all the instances referenced from + * the given instance. + * + * Range-based loops should fit the vast majority of the use cases: + * \code + * std::shared_ptr env = ...; + * for (const Error& error : RecursiveVerification(env)) { + * report_somehow(error); + * } + * \endcode + * + * We use const references to shared pointers here for efficiency. Since + * we do not make a copy of \p that shared pointer, it is very important that + * the given shared pointer outlives the verification, lest cause undefined behavior. + * See these StackOverflow questions: + * * https://stackoverflow.com/questions/12002480/passing-stdshared-ptr-to-constructors/12002668#12002668 + * * https://stackoverflow.com/questions/3310737/should-we-pass-a-shared-ptr-by-reference-or-by-value + * * https://stackoverflow.com/questions/37610494/passing-const-shared-ptrt-versus-just-shared-ptrt-as-parameter + */ +class RecursiveVerification : public IVerification { + public: + RecursiveVerification( + const std::shared_ptr& instance + ); + + Iterator begin() const override; + const Iterator& end() const override; + + ~RecursiveVerification() override = default; + private: + const std::shared_ptr& instance_; +}; // class RecursiveVerification + +} // namespace verification +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_VERIFICATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/visitation.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/visitation.cpp new file mode 100644 index 000000000..2d89c340a --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/visitation.cpp @@ -0,0 +1,109 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/types.hpp" +#include "aas_core/aas_3_0/stringification.hpp" +#include "aas_core/aas_3_0/visitation.hpp" + +#pragma warning(push, 0) +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { +namespace visitation { + +// region AbstractVisitor + +void AbstractVisitor::Visit( + const std::shared_ptr& that +) { + // NOTE (mristin): + // We have to dynamically cast the pointers due to the virtual multiple + // inheritance, and also because we used shared pointers for references. + // If we used constant references instead of shared pointers, we could use + // a pattern such as double dispatch. However, this has the limitation that + // it would prevent us from collecting the instances in the visitor, such that + // they outlive the original structures. + + switch (that->model_type()) { + case types::ModelType::kMyClass: + VisitMyClass( + std::dynamic_pointer_cast< + types::IMyClass + >(that) + ); + break; + case types::ModelType::kListOfPrimitives: + VisitListOfPrimitives( + std::dynamic_pointer_cast< + types::IListOfPrimitives + >(that) + ); + break; + default: + throw std::logic_error( + common::Concat( + "Unexpected model type: ", + std::to_string( + static_cast(that->model_type()) + ) + ) + ); + } +} + +// endregion + +// region PassThroughVisitor + +void PassThroughVisitor::VisitMyClass( + const std::shared_ptr& +) { + // No properties to be passed through. +} + +void PassThroughVisitor::VisitListOfPrimitives( + const std::shared_ptr& that +) { + // mutable_strings + for ( + const std::wstring& item : + that->mutable_strings() + ) { + Visit(item); + } + + // mutable_integers + for ( + int64_t item : + that->mutable_integers() + ) { + Visit(item); + } + + // mutable_booleans + for ( + bool item : + that->mutable_booleans() + ) { + Visit(item); + } + + // mutable_classes + for ( + const std::shared_ptr& item : + that->mutable_classes() + ) { + Visit(item); + } +} + +// endregion + +} // namespace visitation +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/visitation.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/visitation.hpp new file mode 100644 index 000000000..69441667c --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/visitation.hpp @@ -0,0 +1,93 @@ +#ifndef AAS_CORE_AAS_3_0_VISITATION_GUARD_ +#define AAS_CORE_AAS_3_0_VISITATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/types.hpp" + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup visitation Iterate and modify instances through visitors. + * @{ + */ +namespace visitation { + +/** + * Provide an interface for a recursive mutating visitor on an instance. + */ +class IVisitor { + public: + /** + * Visit \p that instance and recursively visit all the instances + * referenced from \p that instance. + * + * We use const references to shared pointers here for efficiency in case you want, + * say, to share ownership over instances in your own external containers. Since + * we do not make copies of the shared pointers, it is very important that + * the given shared pointers outlive the visitor, lest cause undefined behavior. + * See these StackOverflow questions: + * * https://stackoverflow.com/questions/12002480/passing-stdshared-ptr-to-constructors/12002668#12002668 + * * https://stackoverflow.com/questions/3310737/should-we-pass-a-shared-ptr-by-reference-or-by-value + * * https://stackoverflow.com/questions/37610494/passing-const-shared-ptrt-versus-just-shared-ptrt-as-parameter + * + * Changing the references during the visitation results in undefined + * behavior. This follows how STL deals with modifications to containers, see: + * https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers + * + * \param that instance to be visited recursively + */ + virtual void Visit(const std::shared_ptr& that) = 0; + virtual ~IVisitor() = default; + + protected: + virtual void VisitMyClass( + const std::shared_ptr& that + ) = 0; + virtual void VisitListOfPrimitives( + const std::shared_ptr& that + ) = 0; +}; // class IVisitor + +/** + * Provide an abstract recursive mutating visitor on an instance. + */ +class AbstractVisitor + : public IVisitor { + public: + void Visit(const std::shared_ptr& that) override; + ~AbstractVisitor() override = default; +}; // class AbstractVisitor + +/** + * \brief Provide a mutating, recursive and no-op visitor on an instance. + * + * Usually, you want to inherit from this visitor and override one or more of its + * visitation methods. + */ +class PassThroughVisitor + : public AbstractVisitor { + public: + ~PassThroughVisitor() override = default; + + protected: + void VisitMyClass( + const std::shared_ptr& that + ) override; + void VisitListOfPrimitives( + const std::shared_ptr& that + ) override; +}; // class PassThroughVisitor + +} // namespace visitation +/**@*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_VISITATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.cpp new file mode 100644 index 000000000..0f876b94f --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.cpp @@ -0,0 +1,84 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/wstringification.hpp" + +#pragma warning(push, 0) +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { +namespace wstringification { + +const std::unordered_map< + std::wstring, + types::ModelType +> kModelTypeFromWstringMap = { + { + L"MyClass", + types::ModelType::kMyClass + }, + { + L"ListOfPrimitives", + types::ModelType::kListOfPrimitives + } +}; + +common::optional ModelTypeFromWstring( + const std::wstring& text +) { + const auto it = kModelTypeFromWstringMap.find( + text + ); + if (it == kModelTypeFromWstringMap.end()) { + return {}; + } + return it->second; +} + +types::ModelType MustModelTypeFromWstring( + const std::wstring& text +) { + const auto it = kModelTypeFromWstringMap.find( + text + ); + if (it == kModelTypeFromWstringMap.end()) { + throw std::invalid_argument( + common::WstringToUtf8( + common::Concat( + L"Unexpected ModelType literal: ", + text + ) + ) + ); + } + return it->second; +} + +std::wstring to_wstring( + types::ModelType model_type +) { + switch (model_type) { + case types::ModelType::kMyClass: + return L"MyClass"; + case types::ModelType::kListOfPrimitives: + return L"ListOfPrimitives"; + default: + throw std::invalid_argument( + common::Concat( + "Unexpected ModelType literal: ", + std::to_string( + static_cast(model_type) + ) + ) + ); + } +} + +} // namespace wstringification +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.hpp new file mode 100644 index 000000000..161bb7245 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/wstringification.hpp @@ -0,0 +1,65 @@ +#ifndef AAS_CORE_AAS_3_0_WSTRINGIFICATION_GUARD_ +#define AAS_CORE_AAS_3_0_WSTRINGIFICATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup wstringification De/wstringify to and from wstrings (where applicable). + * @{ + */ +namespace wstringification { + +/** + * Try to parse the \p text as a model type literal. + * + * \param text to be parsed + * \return literal, or nothing, if \p text invalid + */ +common::optional ModelTypeFromWstring( + const std::wstring& text +); + +/** + * Parse the \p text as a model type literal. + * + * \param text to be parsed + * \return literal + * \throw std::invalid_argument if \p text invalid + */ +types::ModelType MustModelTypeFromWstring( + const std::wstring& text +); + +/** + * Translate the enumeration literal \p model_type to text. + * + * \param model_type to be converted into text + * \return text representation of \p model_type + * \throw std::invalid_argument if \p model_type invalid + */ +std::wstring to_wstring( + types::ModelType model_type +); + +} // namespace wstringification +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_WSTRINGIFICATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.cpp b/test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.cpp new file mode 100644 index 000000000..890d01e30 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.cpp @@ -0,0 +1,4718 @@ +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/stringification.hpp" +#include "aas_core/aas_3_0/wstringification.hpp" +#include "aas_core/aas_3_0/xmlization.hpp" + +#pragma warning(push, 0) +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#pragma warning(pop) + +static_assert( + !std::is_same::value, + "Expected Expat to be compiled with UTF-8 support, i.e., that character is " + "stored as char internally, " + "but Expat was compiled to store characters internally as UTF-16." +); + +static_assert( + std::is_same::value, + "Expected Expat to be compiled with UTF-8 support, i.e., that " + "character is stored as char internally, " + "but it was not." +); + +namespace aas_core { +namespace aas_3_0 { +namespace xmlization { + +const std::string kNamespace( // NOLINT(cert-err58-cpp) + "https://admin-shell.io/aas/3/0" +); + +// region De-serialization + +// region struct ElementSegment + +ElementSegment::ElementSegment( + std::wstring a_name +) : + name(std::move(a_name)) { + // Intentionally empty. +} + +std::wstring ElementSegment::ToWstring() const { + size_t out_len = 0; + for (const wchar_t character : name) { + switch (character) { + // NOTE (mristin): + // We use sizeof on *strings* instead of *wide strings* to get + // the number of *characters*. Otherwise, if we used wide strings, + // we would obtain the wrong number of characters with `sizeof` + // as we would count bytes instead of characters, which differ + // in wide strings due to encoding. + + case L'&': { + out_len += sizeof("&"); + break; + } + case L'/': { + out_len += sizeof("/"); + break; + } + case L'<': { + out_len += sizeof("<"); + break; + } + case L'>': { + out_len += sizeof(">"); + break; + } + case L'"': { + out_len += sizeof("""); + break; + } + case L'\'': { + out_len += sizeof("'"); + break; + } + default: + ++out_len; + break; + } + } + + // NOTE (mristin): + // We assume here that XML encoding is always *longer* than + // the original text. + if (out_len == name.size()) { + return name; + } + + std::wstring out; + out.reserve(out_len); + + for (const wchar_t character : name) { + switch (character) { + case L'&': + out.append(L"&"); + break; + case L'/': + out.append(L"/"); + break; + case L'<': + out.append(L"<"); + break; + case L'>': + out.append(L">"); + break; + case L'"': + out.append(L"""); + break; + case L'\'': + out.append(L"'"); + break; + default: + out.push_back(character); + break; + } + } + + return out; +} + +std::unique_ptr ElementSegment::Clone() const { + return common::make_unique(*this); +} + +// endregion struct ElementSegment + +// region struct IndexSegment + +IndexSegment::IndexSegment( + size_t an_index +) : + index(an_index) { + // Intentionally empty. +} + +std::wstring IndexSegment::ToWstring() const { + return common::Concat( + L"*[", + std::to_wstring(index), + L"]" + ); +} + +std::unique_ptr IndexSegment::Clone() const { + return common::make_unique(*this); +} + +// endregion struct IndexSegment + +// region struct Path + +Path::Path() { + // Intentionally empty. +} + +Path::Path(const Path& other) { + for (const std::unique_ptr& segment : other.segments) { + segments.emplace_back(segment->Clone()); + } +} + +Path::Path(Path&& other) { + segments = std::move(other.segments); +} + +Path& Path::operator=(const Path& other) { + segments.clear(); + for (const std::unique_ptr& segment : other.segments) { + segments.emplace_back(segment->Clone()); + } + return *this; +} + +Path& Path::operator=(Path&& other) { + if (this != &other) { + segments = std::move(other.segments); + } + return *this; +} + +std::wstring Path::ToWstring() const { + if (segments.empty()) { + return L""; + } + + std::vector parts; + parts.reserve(segments.size() * 2 - 1); + + auto it = segments.begin(); + + parts.emplace_back((*it)->ToWstring()); + ++it; + + for (; it != segments.end(); ++it) { + parts.emplace_back(L"/"); + parts.emplace_back((*it)->ToWstring()); + } + + size_t out_len = 0; + for (const std::wstring& part : parts) { + out_len += part.size(); + } + + std::wstring out; + out.reserve(out_len); + for (const std::wstring& part : parts) { + out.append(part); + } + + return out; +} + +// region DeserializationError + +DeserializationError::DeserializationError( + std::wstring a_cause +) : + cause(a_cause) { + // Intentionally empty. +} + +DeserializationError::DeserializationError( + std::wstring a_cause, + Path a_path +) : + cause(a_cause), + path(a_path) { + // Intentionally empty. +} + +// endregion DeserializationError + +enum class NodeKind : std::uint32_t { + // Nodes of the kind `Bof` represent the beginning-of-input, before any read. + Bof = 0, + Start = 1, + Stop = 2, + Text = 3, + // Nodes of the kind `Eof` represent the end-of-input. + Eof = 4, + // Nodes of the kind `Error` represent low-level errors in the XML parsing. + Error = 5 +}; // enum class NodeKind + +const std::unordered_map< + NodeKind, + std::string +> kNodeKindToHumanReadableString = { + {NodeKind::Bof, "a beginning-of-input"}, + {NodeKind::Start, "a start element"}, + {NodeKind::Stop, "a stop element"}, + {NodeKind::Text, "a text"}, + {NodeKind::Eof, "an end-of-input"}, + {NodeKind::Error, "an error"}, +}; + +const std::string& NodeKindToHumanReadableString(NodeKind kind) { + auto it = kNodeKindToHumanReadableString.find(kind); + if (it == kNodeKindToHumanReadableString.end()) { + throw std::invalid_argument( + common::Concat( + "Unexpected node kind: ", + std::to_string( + static_cast(kind) + ) + ) + ); + } + + return it->second; +} + +// region Nodes + +/** + * Model a node in an XML document. + */ +class INode { + public: + /** + * @return the kind of the node, used instead of much slower RTTI. + */ + virtual NodeKind kind() const = 0; + virtual ~INode() = default; +}; // class INode + +/** + * Model the beginning of the input, before anything was read. + */ +class BofNode : public INode { + public: + NodeKind kind() const override { return NodeKind::Bof; } + + ~BofNode() override = default; +}; // class StartNode + +/** + * Model a start of an XML element. + */ +class StartNode : public INode { + public: + explicit StartNode( + std::string a_name + ) : + name(std::move(a_name)) { + // Intentionally empty. + } + + NodeKind kind() const override { return NodeKind::Start; } + + /** + * Name of the start element, stripped of the expected XML namespace + */ + const std::string name; + + ~StartNode() override = default; +}; // class StartNode + +/** + * Model a stop of an XML element. + */ +class StopNode : public INode { + public: + explicit StopNode( + std::string a_name + ) : + name(std::move(a_name)) { + // Intentionally empty. + } + + NodeKind kind() const override { return NodeKind::Stop; } + + /** + * Name of the stop element, stripped of the expected XML namespace + */ + const std::string name; + + ~StopNode() override = default; +}; // class StopNode + +/** + * Model a text node. + */ +class TextNode : public INode { + public: + explicit TextNode( + std::string a_text + ) : + text(std::move(a_text)) { + // Intentionally empty. + } + + NodeKind kind() const override { return NodeKind::Text; } + + /** + * UTF-8 encoded XML text somewhere within an XML element + */ + const std::string text; + + ~TextNode() override = default; +}; // class TextNode + +/** + * Model an end-of-input. + */ +class EofNode : public INode { + public: + NodeKind kind() const override { return NodeKind::Eof; } + + ~EofNode() override = default; +}; // class EofNode + +/** + * Model a low-level XML parsing error. + */ +class ErrorNode : public INode { + public: + ErrorNode( + size_t a_line, + size_t a_column, + std::string a_cause + ) : + line(a_line), + column(a_column), + cause(std::move(a_cause)) { + // Intentionally empty. + } + + NodeKind kind() const override { return NodeKind::Error; } + + const size_t line; + const size_t column; + + // Cause of the error as UTF-8 encoded string + const std::string cause; + + ~ErrorNode() override = default; +}; // class ErrorNode + +// endregion Nodes + +// region Reading + +// region class Reader + +/** + * Structure the data passed over to Expat XML reader. + */ +struct OurData { + bool additional_attributes; + size_t buffer_size; + XML_Parser parser; + + std::deque >& node_buffer; + + bool stopped = false; + + OurData( + bool the_additional_attributes, + size_t a_buffer_size, + XML_Parser a_parser, + std::deque >& a_node_buffer + ) : + additional_attributes(the_additional_attributes), + buffer_size(a_buffer_size), parser(a_parser), + node_buffer(a_node_buffer) { + // Intentionally empty. + } +}; // struct OurData + +/** + * \brief Read XML in form of nodes, whereas text nodes are fragmented. + * + * We need a more abstract approach since the Expat library is too low-level + * to parse complex models. + * + * Expat does not read the whole content of a text node in memory, but + * we need to process the whole text during the XML de-serialization. Hence, + * we keep on reading until we read the complete text. This has repercussions + * on memory usage, as the the text will be held in three copies(one copy in + * the Expat buffer, second copy in our internal buffer in which we + * incrementally feed in the fragments, and the third copy is the final merged + * text). + */ +class Reader { + public: + Reader( + std::istream& is, + const ReadingOptions& options + ); + + /** + * Set up the reader for the XML parsing and read the first node. + */ + void Initialize(); + + /** + * Read the next node in the document. + */ + void Read(); + + /** + * @return the node which has been read last + */ + const INode& node() const; + + /** + * @return the node which has been read last moved out of this reader + */ + std::unique_ptr moved_node(); + + ~Reader(); + + private: + const bool additional_attributes_; + const size_t buffer_size_; + std::istream& is_; + + XML_Parser parser_; + std::unique_ptr our_data_; + + // Node buffer does not include the current node. + std::deque> node_buffer_; + + // Current node is never null. + std::unique_ptr current_; + + // Set if the current node is end-of-input + bool eof_; + + // Set if the current node is an error + bool error_; + + void SetCurrentAndEofAndError(std::unique_ptr node); + + // Re-usable buffer to keep a chunk of the data read from the input + std::vector chunk_; +}; // class Reader + +Reader::Reader( + std::istream& is, + const ReadingOptions& options +) : + additional_attributes_(options.additional_attributes), + buffer_size_(options.buffer_size), + is_(is), + parser_(nullptr), + current_(common::make_unique()), + eof_(false), + error_(false) { + // Intentionally empty. +} + +const char kNamespaceSeparator = '|'; + +void XMLCALL OnStartElement( + void* user_data, + const char* name, + const char* attributes[] +) { + auto our_data = static_cast(user_data); + + // NOTE (mristin): + // Since Expat continues parsing and adding nodes even if the parsing is + // suspended (see the documentation of `XML_StopParser`), we have to ignore + // any further events. + if (our_data->stopped) { + return; + } + + const std::string name_str(name); + + size_t separator_i = name_str.find(kNamespaceSeparator); + if (separator_i == std::string::npos || separator_i == 0) { + std::string message = common::Concat( + "The namespace is missing in the start element <", + name_str, + ">" + ); + + our_data->node_buffer.emplace_back( + common::make_unique( + XML_GetCurrentLineNumber(our_data->parser), + XML_GetCurrentColumnNumber(our_data->parser), + message + ) + ); + + XML_StopParser(our_data->parser, false); + our_data->stopped = true; + return; + } + + if (name_str.compare(0, separator_i, kNamespace) != 0) { + std::string message = common::Concat( + "We expected the XML namespace ", + kNamespace, + ", but we got the namespace ", + name_str.substr(0, separator_i), + " in the start element <", + name_str.substr(separator_i + 1), + ">" + ); + + our_data->node_buffer.emplace_back( + common::make_unique( + XML_GetCurrentLineNumber(our_data->parser), + XML_GetCurrentColumnNumber(our_data->parser), + message + ) + ); + + XML_StopParser(our_data->parser, false); + our_data->stopped = true; + return; + } + + if ( + attributes[0] != nullptr + && !(our_data->additional_attributes) + ) { + std::string message = common::Concat( + "Additional attributes are not allowed, " + "but the attribute ", + attributes[0], + " was read in the start element <", + name_str.substr(separator_i + 1), + ">" + ); + + our_data->node_buffer.emplace_back( + common::make_unique( + XML_GetCurrentLineNumber(our_data->parser), + XML_GetCurrentColumnNumber(our_data->parser), + message + ) + ); + + XML_StopParser(our_data->parser, false); + our_data->stopped = true; + return; + } + + our_data->node_buffer.emplace_back( + common::make_unique( + name_str.substr(separator_i + 1) + ) + ); +} + +void XMLCALL OnStopElement( + void* user_data, + const char* name +) { + auto* our_data = static_cast(user_data); + + // NOTE (mristin): + // Since Expat continues parsing and adding nodes even if the parsing is + // suspended (see the documentation of `XML_StopParser`), we have to ignore + // any further events. + if (our_data->stopped) { + return; + } + + const std::string name_str(name); + + size_t separator_i = name_str.find(kNamespaceSeparator); + if (separator_i == std::string::npos || separator_i == 0) { + std::string message = common::Concat( + "The namespace is missing in the stop element " + ); + + our_data->node_buffer.emplace_back( + common::make_unique( + XML_GetCurrentLineNumber(our_data->parser), + XML_GetCurrentColumnNumber(our_data->parser), + message + ) + ); + + XML_StopParser(our_data->parser, false); + our_data->stopped = true; + return; + } + + if (name_str.compare(0, separator_i, kNamespace) != 0) { + std::string message = common::Concat( + "We expected the XML namespace ", + kNamespace, + ", but we got the namespace ", + name_str.substr(0, separator_i), + " in the stop element " + ); + + our_data->node_buffer.emplace_back( + common::make_unique( + XML_GetCurrentLineNumber(our_data->parser), + XML_GetCurrentColumnNumber(our_data->parser), + message + ) + ); + + XML_StopParser(our_data->parser, false); + our_data->stopped = true; + return; + } + + our_data->node_buffer.emplace_back( + common::make_unique( + name_str.substr(separator_i + 1) + ) + ); +} + +void XMLCALL OnText( + void* user_data, + const char* val, + int len +) { + auto our_data = static_cast(user_data); + + // NOTE (mristin): + // Since Expat continues parsing and adding nodes even if the parsing is + // suspended (see the documentation of `XML_StopParser`), we have to ignore + // any further events. + if (our_data->stopped) { + return; + } + + our_data->node_buffer.emplace_back( + common::make_unique( + std::string(val, len) + ) + ); +} + +void Reader::Initialize() { + // NOTE (mristin): + // We set up the underlying parser here instead of the constructor + // to avoid throwing exceptions in the constructor. + + if (parser_ != nullptr) { + throw std::logic_error( + "You are trying to re-initialize an initialized XML reader." + ); + } + + if ( + buffer_size_ + > static_cast( + (std::numeric_limits::max)() + ) + ) { + throw std::invalid_argument( + common::Concat( + "Expat library expects the buffer size as int, " + "but the given buffer size ", + std::to_string(buffer_size_), + " does not fit in an int as it is larger than the maximum int ", + std::to_string(std::numeric_limits::max()) + ) + ); + } + + parser_ = XML_ParserCreateNS(nullptr, kNamespaceSeparator); + our_data_ = common::make_unique( + additional_attributes_, + buffer_size_, + parser_, + node_buffer_ + ); + + XML_SetUserData(parser_, our_data_.get()); + XML_SetElementHandler( + parser_, + OnStartElement, + OnStopElement + ); + XML_SetCharacterDataHandler(parser_, OnText); + + chunk_.resize(buffer_size_); + + Read(); +} + +void Reader::Read() { + if (parser_ == nullptr) { + throw std::logic_error( + "You are trying to read from an uninitialized XML reader" + ); + } + + if (eof_) { + throw std::logic_error( + "The XML reader reached the end-of-input, " + "but you called Read()" + ); + } + + if (error_) { + throw std::logic_error( + "There was an error while reading XML, " + "but you called Read() again" + ); + } + + while (node_buffer_.empty()) { + // NOTE (mristin): + // We read and parse the next chunk of input, until we parsed a whole node. + // The text, however, will be fragmented by Expat's design. + + is_.read(&(chunk_[0]), buffer_size_); + + const std::streamsize actual_bytes_read = is_.gcount(); + + if (is_.bad()) { + SetCurrentAndEofAndError( + common::make_unique( + 0, + 0, + "Failed to read from the input" + ) + ); + return; + } + + if (actual_bytes_read == 0) { + if (is_.eof()) { + SetCurrentAndEofAndError(common::make_unique()); + return; + } else { + SetCurrentAndEofAndError( + common::make_unique( + 0, + 0, + "Read zero bytes from the input, " + "but the input is neither eof() nor bad()" + ) + ); + return; + } + } else { + const bool done = is_.eof(); + + if (actual_bytes_read > std::numeric_limits::max()) { + std::string message = common::Concat( + "Expat library expects the buffer size as int, ", + "but the actual number of bytes read ", + std::to_string(actual_bytes_read), + " does not fit in an int as it is larger than the maximum int ", + std::to_string(std::numeric_limits::max()) + ); + + throw std::runtime_error(message); + } + + const auto actual_bytes_read_int = static_cast(actual_bytes_read); + + XML_Status status = XML_Parse( + parser_, + &(chunk_[0]), + actual_bytes_read_int, + done + ); + + if (status == XML_STATUS_ERROR) { + XML_Error error_code = XML_GetErrorCode(parser_); + + if (error_code == XML_ERROR_ABORTED) { + if (node_buffer_.empty()) { + throw std::logic_error( + "The XML parsing was aborted, " + "so we expected an error node on the buffer, " + "but the buffer was empty" + ); + } + + if (node_buffer_.back()->kind() != NodeKind::Error) { + std::string message = common::Concat( + "The XML parsing was aborted, " + "so we expected an error node on the buffer, " + "but we got ", + NodeKindToHumanReadableString(node_buffer_.back()->kind()) + ); + + throw std::logic_error(message); + } + } else { + const XML_LChar* error_str = XML_ErrorString(error_code); + + node_buffer_.emplace_back( + common::make_unique( + XML_GetCurrentLineNumber(parser_), + XML_GetCurrentColumnNumber(parser_), + std::string(error_str) + ) + ); + } + } else { + if (done) { + node_buffer_.emplace_back(common::make_unique()); + } + } + } + } + + SetCurrentAndEofAndError(std::move(node_buffer_.front())); + node_buffer_.pop_front(); +} + +const INode& Reader::node() const { + return *current_; +} + +std::unique_ptr Reader::moved_node() { + return std::move(current_); +} + +Reader::~Reader() { + if (parser_ != nullptr) { + XML_ParserFree(parser_); + } +} + +void Reader::SetCurrentAndEofAndError( + std::unique_ptr node +) { + current_ = std::move(node); + + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wswitch" + #endif + switch (current_->kind()) { + case NodeKind::Eof: + eof_ = true; + break; + case NodeKind::Error: + error_ = true; + break; + } + #ifdef __clang__ + #pragma clang diagnostic pop + #endif +} + +// endregion class Reader + +// region class ReaderMergingText + +/** + * \brief Read XML in forms of nodes, with text nodes read in whole. + * + * This is a reader on top of the \ref Reader which keeps the text fragments + * in the buffer. We need to process the text in whole during the XML + * de-serialization, so this buffering is necessary. However, this means that + * the text is kept in four copies (one partial copy in Expat buffer, + * another partial copy as fragmented text nodes in the underlying \ref Reader + * instance, yet another copy in the internal buffer of this instance, and + * finally the fourth copy as the merged complete text). + */ +class ReaderMergingText { + public: + ReaderMergingText( + std::istream& is, + const ReadingOptions& options + ); + + /** + * Set up the reader for the XML parsing and read the first node. + */ + void Initialize(); + + /** + * Read the next node in the document. + */ + void Read(); + + /** + * @return the node which has been read last + */ + const INode& node() const; + + /** + * @return set if the current node represents an error + */ + bool error() const; + + /** + * @return set if the current node represents an end-of-input + */ + bool eof() const; + + private: + bool initialized_; + Reader reader_; + + std::unique_ptr current_; + std::unique_ptr look_ahead_; + + // Assuming that the underlying reader points to a text node, + // read all the consecutive text nodes and set the look-ahead node + void ReadAndMergeAllTextAndSetLookahead(); + + bool error_; + bool eof_; + void SetCurrentAndEofAndError( + std::unique_ptr node + ); +}; // class ReaderMergingText + +ReaderMergingText::ReaderMergingText( + std::istream& is, + const ReadingOptions& options +) : + initialized_(false), + reader_(is, options), + current_(common::make_unique()), + error_(false), + eof_(false) { + // Intentionally empty. +} + +void ReaderMergingText::Initialize() { + if (initialized_) { + throw std::logic_error( + "You are trying to initialize " + "an already initialized ReaderMergingText" + ); + } + + reader_.Initialize(); + + // NOTE (mristin): + // The `reader_` has already read a node. Hence, we need to parse it here + // separately from `ReaderMergingText::Read` method. + + if (reader_.node().kind() != NodeKind::Text) { + SetCurrentAndEofAndError(reader_.moved_node()); + } else { + ReadAndMergeAllTextAndSetLookahead(); + } + + initialized_ = true; +} + +void ReaderMergingText::Read() { + if (!initialized_) { + throw std::logic_error( + "You are reading from an uninitialized ReaderMergingText" + ); + } + + if (eof()) { + throw std::logic_error( + "You are trying to read from a ReaderMergingText, " + "but it reached the end-of-input" + ); + } + + if (error()) { + throw std::logic_error( + "You are trying to read from a ReaderMergingText, " + "but an error already occurred" + ); + } + + if (look_ahead_ != nullptr) { + SetCurrentAndEofAndError(std::move(look_ahead_)); + return; + } + + reader_.Read(); + if (reader_.node().kind() != NodeKind::Text) { + SetCurrentAndEofAndError(reader_.moved_node()); + } else { + ReadAndMergeAllTextAndSetLookahead(); + } +} + +const INode& ReaderMergingText::node() const { + return *current_; +} + +bool ReaderMergingText::error() const { + return error_; +} + +bool ReaderMergingText::eof() const { + return eof_; +} + +void ReaderMergingText::ReadAndMergeAllTextAndSetLookahead() { + if (reader_.node().kind() != NodeKind::Text) { + std::string message = common::Concat( + "Expected the current node in the reader " + "underlying ReaderMergingText to be a text, " + "but it was ", + NodeKindToHumanReadableString(reader_.node().kind()) + ); + + throw std::logic_error(message); + } + + std::deque text_buffer; + + while (reader_.node().kind() == NodeKind::Text) { + const TextNode& fragment_text_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >( + reader_.node() + ) + ); + + text_buffer.emplace_back(fragment_text_node.text); + + reader_.Read(); + } + look_ahead_ = reader_.moved_node(); + + size_t size = 0; + for (const std::string& fragment : text_buffer) { + size += fragment.size(); + } + + std::string text; + text.reserve(size); + while (!text_buffer.empty()) { + text.append(text_buffer.front()); + text_buffer.pop_front(); + } + + SetCurrentAndEofAndError(common::make_unique(text)); +} + +void ReaderMergingText::SetCurrentAndEofAndError(std::unique_ptr node) { + current_ = std::move(node); + + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wswitch" + #endif + switch (current_->kind()) { + case NodeKind::Eof:eof_ = true; + break; + case NodeKind::Error:error_ = true; + break; + } + #ifdef __clang__ + #pragma clang diagnostic pop + #endif +} + +// endregion class ReaderMergingText + +// endregion Reading + +// region Forward declarations of de-serialization functions + +// NOTE (mristin): +// We make forward declarations of de-serialization functions so that they can be +// called in any order. + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> MyClassFromElement( + ReaderMergingText& reader +); + +template < + typename T, + typename std::enable_if< + std::is_base_of::value + >::type* = nullptr +> +std::pair< + common::optional >, + common::optional +> MyClassFromSequence( + ReaderMergingText& reader +); + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> ListOfPrimitivesFromElement( + ReaderMergingText& reader +); + +template < + typename T, + typename std::enable_if< + std::is_base_of::value + >::type* = nullptr +> +std::pair< + common::optional >, + common::optional +> ListOfPrimitivesFromSequence( + ReaderMergingText& reader +); + +// endregion Forward declarations of de-serialization functions + +/** + * Map XML class names to model types. + */ +const std::unordered_map< + std::string, + types::ModelType +> kElementNameToModelType = { + { + "myClass", + types::ModelType::kMyClass + }, + { + "listOfPrimitives", + types::ModelType::kListOfPrimitives + } +}; + +common::optional ModelTypeFromElementName( + const std::string& element_name +) { + auto it = kElementNameToModelType.find(element_name); + if (it == kElementNameToModelType.end()) { + return common::nullopt; + } + + return it->second; +} + +std::string NodeToHumanReadableString( + const INode& node +) { + switch (node.kind()) { + case NodeKind::Bof: + return "beginning-of-input"; + + case NodeKind::Start: { + const StartNode& start_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(node) + ); + + return common::Concat( + "a start node <", + start_node.name, + ">" + ); + } + + case NodeKind::Stop: { + const StopNode& stop_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StopNode& + >(node) + ); + + return common::Concat( + "a stop node " + ); + } + + case NodeKind::Text: + return "an XML text"; + + case NodeKind::Eof: + return "end-of-input"; + + case NodeKind::Error: + return "an XML error"; + + default: + throw std::invalid_argument( + common::Concat( + "Unexpected node kind: ", + std::to_string( + static_cast(node.kind()) + ) + ) + ); + } +} + +std::wstring NodeToHumanReadableWstring( + const INode& node +) { + switch (node.kind()) { + case NodeKind::Bof: + return L"beginning-of-input"; + + case NodeKind::Start: { + const StartNode& start_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(node) + ); + + return common::Concat( + L"a start node <", + common::Utf8ToWstring(start_node.name), + L">" + ); + } + + case NodeKind::Stop: { + const StopNode& stop_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StopNode& + >(node) + ); + + return common::Concat( + L"a stop node " + ); + } + + case NodeKind::Text: + return L"an XML text"; + + case NodeKind::Eof: + return L"end-of-input"; + + case NodeKind::Error: + return L"an XML error"; + + default: + throw std::invalid_argument( + common::Concat( + "Unexpected node kind: ", + std::to_string( + static_cast(node.kind()) + ) + ) + ); + } +} + +/** + * Check that the given node is a stop node and that its name corresponds to + * the expected name. + */ +bool IsStopNodeWithName( + const INode& node, + const std::string& expected_name +) { + if (node.kind() != NodeKind::Stop) { + return false; + } + + const std::string& name( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StopNode& + >(node).name + ); + if (name != expected_name) { + return false; + } + + return true; +} + +template < + typename T +> +std::pair< + common::optional, + common::optional +> InstanceAndNoDeserializationError( + T&& instance +) { + return std::make_pair< + common::optional, + common::optional + >( + std::move(instance), + common::nullopt + ); +} + +template < + typename T +> std::pair< + common::optional, + common::optional +> NoInstanceAndDeserializationErrorWithCause( + std::wstring cause +) { + return std::make_pair< + common::optional, + common::optional + >( + common::nullopt, + common::make_optional( + std::move(cause) + ) + ); +} + +DeserializationError DeserializationErrorFromReader( + ReaderMergingText& reader +) { + if (reader.node().kind() != NodeKind::Error) { + throw std::logic_error( + common::Concat( + "Expected an error node at the reader cursor, but got ", + NodeToHumanReadableString(reader.node()) + ) + ); + } + + const auto error_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const ErrorNode& + >(reader.node()) + ); + + return DeserializationError( + common::Utf8ToWstring( + error_node.cause + ) + ); +} + +template < + typename T +> +std::pair< + common::optional, + common::optional +> NoInstanceAndDeserializationErrorFromReader( + ReaderMergingText& reader +) { + if (reader.node().kind() != NodeKind::Error) { + throw std::logic_error( + common::Concat( + "Expected an error node at the reader cursor, but got ", + NodeToHumanReadableString(reader.node()) + ) + ); + } + + DeserializationError error = DeserializationErrorFromReader( + reader + ); + + return std::make_pair( + common::nullopt, + common::make_optional( + std::move(error) + ) + ); +} + +template < + typename T +> +std::pair< + common::optional, + common::optional +> NoInstanceAndDeserializationError( + DeserializationError error +) { + return std::make_pair( + common::nullopt, + common::make_optional( + std::move(error) + ) + ); +} + +void PrependElementSegmentToDeserializationError( + const std::string& name, + DeserializationError& deserialization_error +) { + deserialization_error.path.segments.emplace_front( + common::make_unique( + common::Utf8ToWstring(name) + ) + ); +} + +common::optional CheckReaderAtEof( + const ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in CheckReaderAtEof. " + "CheckReaderAtEof expects no reader error at entry." + ); + } + #endif + + if (reader.node().kind() != NodeKind::Eof) { + return common::make_optional( + common::Concat( + L"Expected end-of-input, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + return common::nullopt; +} + +/** + * \brief Skip the beginning-of-file (BoF) and read a node. + * + * Do nothing if the cursor points to a non-BoF node. + * + * Return an error if the reader produced an error. + */ +common::optional SkipBof( + ReaderMergingText& reader +) { + if (reader.node().kind() != NodeKind::Bof) { + return common::nullopt; + } + + reader.Read(); + if (reader.node().kind() == NodeKind::Error) { + return DeserializationErrorFromReader(reader); + } + + return common::nullopt; +} + +/** + * Return `true` if all characters are whitespace in the UTF-8-encoded text. + */ +bool IsWhitespace(const std::string& utf8_text) { + for (const char character : utf8_text) { + switch (character) { + // NOTE (mristin): + // The characters are ordered by their ASCII codes so that + // we allow compilers to optimize. + + // NOTE (mristin): + // Text nodes contain text in UTF-8 which is compatible with ASCII. + // In particular, all characters above ASCII (>127) are encoded with + // all the leading bits set. Hence, it is safe to check for whitespace + // characters in an UTF-8-encoded string using one-byte characters. + // + // See: https://stackoverflow.com/questions/15965811/why-utf8-is-compatible-with-ascii + + case '\t': + case '\n': + case '\r': + case ' ': + // Pass + break; + default: + return false; + } + } + + return true; +} + +/** + * \brief Skip all whitespace text nodes. + * + * Do nothing if the cursor points to a non-text node. + * + * The whitespace includes space, tab, carriage return and newline. + * + * Return an error if the reader produced an error. + */ +common::optional SkipWhitespace( + ReaderMergingText& reader +) { + while (reader.node().kind() == NodeKind::Text) { + const TextNode& text_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >( + reader.node() + ) + ); + + if (!IsWhitespace(text_node.text)) { + break; + } + + reader.Read(); + } + + if (reader.node().kind() == NodeKind::Error) { + return DeserializationErrorFromReader(reader); + } + + return common::nullopt; +} + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> ClassFromElement( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in ClassFromElement. " + "ClassFromElement expects no reader error at entry." + ); + } + #endif + + common::optional error; + + error = SkipBof(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + if (reader.node().kind() != NodeKind::Start) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening an instance " + L"of IClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string name( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(reader.node()).name + ); + + common::optional model_type( + ModelTypeFromElementName(name) + ); + if (!model_type.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Unexpected start element as its name does not correspond " + L"to any model type: ", + common::Utf8ToWstring(name) + ) + ); + } + + // NOTE (mristin): + // We consume the start element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + auto noInstanceAndError = NoInstanceAndDeserializationErrorFromReader< + std::shared_ptr + >( + reader + ); + + PrependElementSegmentToDeserializationError( + name, + *(noInstanceAndError.second) + ); + + return noInstanceAndError; + } + + common::optional< + std::shared_ptr + > instance; + + switch (*model_type) { + case types::ModelType::kMyClass: + std::tie(instance, error) = MyClassFromSequence< + types::IClass + >(reader); + break; + case types::ModelType::kListOfPrimitives: + std::tie(instance, error) = ListOfPrimitivesFromSequence< + types::IClass + >(reader); + break; + default: + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Impossible to de-serialize an instance " + L"of IClass from <", + common::Utf8ToWstring(name), + L">" + ) + ); + } + + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + if (!IsStopNodeWithName(reader.node(), name)) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing an instance " + L"of IClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + const StopNode& stop_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StopNode& + >(reader.node()) + ); + if (stop_node.name != name) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing an instance " + L"of IClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + // NOTE (mristin): + // We consume the stop element. + reader.Read(); + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + return InstanceAndNoDeserializationError( + std::move(*instance) + ); +} + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> MyClassFromElement( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in MyClassFromElement. " + "MyClassFromElement expects no reader error at entry." + ); + } + #endif + + common::optional error; + + error = SkipBof(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + if (reader.node().kind() != NodeKind::Start) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening an instance " + L"of IMyClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string name( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(reader.node()).name + ); + + common::optional model_type( + ModelTypeFromElementName(name) + ); + if (!model_type.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Unexpected start element as its name does not correspond " + L"to any model type: ", + common::Utf8ToWstring(name) + ) + ); + } + + // NOTE (mristin): + // We consume the start element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + auto noInstanceAndError = NoInstanceAndDeserializationErrorFromReader< + std::shared_ptr + >( + reader + ); + + PrependElementSegmentToDeserializationError( + name, + *(noInstanceAndError.second) + ); + + return noInstanceAndError; + } + + common::optional< + std::shared_ptr + > instance; + + switch (*model_type) { + case types::ModelType::kMyClass: + std::tie(instance, error) = MyClassFromSequence< + types::IMyClass + >(reader); + break; + default: + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Impossible to de-serialize an instance " + L"of IMyClass from <", + common::Utf8ToWstring(name), + L">" + ) + ); + } + + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + if (!IsStopNodeWithName(reader.node(), name)) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing an instance " + L"of IMyClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + const StopNode& stop_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StopNode& + >(reader.node()) + ); + if (stop_node.name != name) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing an instance " + L"of IMyClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + // NOTE (mristin): + // We consume the stop element. + reader.Read(); + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + return InstanceAndNoDeserializationError( + std::move(*instance) + ); +} + +std::pair< + common::optional< + std::shared_ptr + >, + common::optional +> ListOfPrimitivesFromElement( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in ListOfPrimitivesFromElement. " + "ListOfPrimitivesFromElement expects no reader error at entry." + ); + } + #endif + + common::optional error; + + error = SkipBof(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + if (reader.node().kind() != NodeKind::Start) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening an instance " + L"of IListOfPrimitives, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string name( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(reader.node()).name + ); + + common::optional model_type( + ModelTypeFromElementName(name) + ); + if (!model_type.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Unexpected start element as its name does not correspond " + L"to any model type: ", + common::Utf8ToWstring(name) + ) + ); + } + + // NOTE (mristin): + // We consume the start element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + auto noInstanceAndError = NoInstanceAndDeserializationErrorFromReader< + std::shared_ptr + >( + reader + ); + + PrependElementSegmentToDeserializationError( + name, + *(noInstanceAndError.second) + ); + + return noInstanceAndError; + } + + common::optional< + std::shared_ptr + > instance; + + switch (*model_type) { + case types::ModelType::kListOfPrimitives: + std::tie(instance, error) = ListOfPrimitivesFromSequence< + types::IListOfPrimitives + >(reader); + break; + default: + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Impossible to de-serialize an instance " + L"of IListOfPrimitives from <", + common::Utf8ToWstring(name), + L">" + ) + ); + } + + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + if (!IsStopNodeWithName(reader.node(), name)) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing an instance " + L"of IListOfPrimitives, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + const StopNode& stop_node( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StopNode& + >(reader.node()) + ); + if (stop_node.name != name) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing an instance " + L"of IListOfPrimitives, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + // NOTE (mristin): + // We consume the stop element. + reader.Read(); + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >(std::move(*error)); + } + + return InstanceAndNoDeserializationError( + std::move(*instance) + ); +} + +// region De-serialize primitives + +const std::unordered_map< + std::string, + bool +> kTextToBool = { + {"true", true}, + {"false", false}, + {"1", true}, + {"0", false} +}; + +std::pair< + common::optional, + common::optional +> DeserializeBool( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in DeserializeBool. " + "DeserializeBool expects no error node." + ); + } + #endif + + if (reader.node().kind() != NodeKind::Text) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:boolean from XML text, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string& text( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >(reader.node()).text + ); + + auto it = kTextToBool.find(text); + if (it == kTextToBool.end()) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:boolean from text, " + L"but got an invalid value: ", + common::Utf8ToWstring(text) + ) + ); + } + + // NOTE (mristin): + // We consume the text node. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + return NoInstanceAndDeserializationErrorFromReader(reader); + } + + return std::make_pair( + it->second, + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> DeserializeInt64( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in DeserializeInt64. " + "DeserializeInt64 expects no error node." + ); + } + #endif + + if (reader.node().kind() != NodeKind::Text) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:long from XML text, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string& text( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >(reader.node()).text + ); + + common::optional deserialized; + + static_assert( + sizeof(int) == 8 + || sizeof(long) == 8 + || sizeof(long long) == 8, + "Neither int nor long nor long long are 8 bytes long, " + "so we do not know how to parse an xs:long." + ); + + try { + // NOTE (mristin): + // We remove the warning C4101 in MSVC with constants. + // See: https://stackoverflow.com/questions/25573996/c4127-conditional-expression-is-constant + const bool sizeof_int_is_8 = sizeof(int) == 8; + const bool sizeof_long_is_8 = sizeof(long) == 8; + const bool sizeof_long_long_is_8 = sizeof(long long) == 8; + + if (sizeof_int_is_8) { + deserialized = std::stoi(text); + } else if (sizeof_long_is_8) { + deserialized = std::stol(text); + } else if (sizeof_long_long_is_8) { + deserialized = std::stoll(text); + } + } catch (std::invalid_argument&) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:long from text, " + L"but got an invalid value: ", + common::Utf8ToWstring(text) + ) + ); + } catch (std::out_of_range&) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:long from text, " + L"but got a value out of the xs:long range: ", + common::Utf8ToWstring(text) + ) + ); + } + + if (!deserialized.has_value()) { + throw std::logic_error( + "Neither int nor long nor long long are 8 bytes long, " + "but this should have been caught earlier in the static assert" + ); + } + + // NOTE (mristin): + // We consume the text node. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + return NoInstanceAndDeserializationErrorFromReader(reader); + } + + return std::make_pair( + deserialized, + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> DeserializeDouble( + ReaderMergingText& reader +) { + static_assert( + sizeof(double) == 8, + "DeserializeDouble expects double to be 8 bytes, " + "but the size of the double is not 8 bytes" + ); + + #ifdef DEBUG + if (node.kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in DeserializeDouble. " + "DeserializeDouble expects no error node." + ); + } + #endif + + if (reader.node().kind() != NodeKind::Text) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:double from XML text, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string& text( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >(reader.node()).text + ); + + double deserialized; + + try { + deserialized = std::stod(text); + } catch (std::invalid_argument&) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:double from text, " + L"but got an invalid value: ", + common::Utf8ToWstring(text) + ) + ); + } catch (std::out_of_range&) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:double from text, " + L"but got a value out of the xs:double range: ", + common::Utf8ToWstring(text) + ) + ); + } + + // NOTE (mristin): + // XSD basic types are not case insensitive and quite strict. + // We follow this strictness in the parsing as well. + // + // See: https://www.w3.org/TR/xmlschema11-2/#double + + const bool invalid_xml( + ( + deserialized == std::numeric_limits::infinity() + && text != "INF" + ) || ( + deserialized == -std::numeric_limits::infinity() + && text != "-INF" + ) || ( + std::isnan(deserialized) + && text != "NaN" + ) + ); + + if (invalid_xml) { + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:double from text, " + L"but got an invalid value: ", + common::Utf8ToWstring(text) + ) + ); + } + + // NOTE (mristin): + // We consume the text node. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + return NoInstanceAndDeserializationErrorFromReader(reader); + } + + return std::make_pair( + deserialized, + common::nullopt + ); +} + +std::pair< + common::optional, + common::optional +> DeserializeWstring( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in DeserializeWstring. " + "DeserializeWstring expects no error node." + ); + } + #endif + + switch (reader.node().kind()) { + case NodeKind::Stop: + // Encountering a stop node means that the string is empty. + return std::make_pair(std::wstring(), common::nullopt); + case NodeKind::Text: + // We pass and continue decoding the text. + break; + default: + return NoInstanceAndDeserializationErrorWithCause( + common::Concat( + L"Expected to parse an xs:string from XML text, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string& text( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >(reader.node()).text + ); + + std::wstring deserialized = common::Utf8ToWstring(text); + + // NOTE (mristin): + // We consume the text node. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + return NoInstanceAndDeserializationErrorFromReader(reader); + } + + return std::make_pair(std::move(deserialized), common::nullopt); +} + +std::pair< + common::optional >, + common::optional +> DeserializeByteArray( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in DeserializeByteArray. " + "DeserializeByteArray expects no error node." + ); + } + #endif + + switch (reader.node().kind()) { + case NodeKind::Stop: + // Encountering a stop node means empty byte array. + return std::make_pair( + std::vector(), + common::nullopt + ); + case NodeKind::Text: + // We pass and continue decoding the byte array. + break; + default: + return NoInstanceAndDeserializationErrorWithCause< + std::vector + >( + common::Concat( + L"Expected to parse an xs:base64Binary from XML text, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string& text( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const TextNode& + >(reader.node()).text + ); + + common::expected< + std::vector, + std::string + > deserialized = stringification::Base64Decode(text); + + if (!deserialized.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::vector + >( + common::Concat( + L"Expected to parse an xs:base64Binary from text, " + L"but the value was invalid: ", + common::Utf8ToWstring(deserialized.error()) + ) + ); + } + + // NOTE (mristin): + // We consume the text node. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + return NoInstanceAndDeserializationErrorFromReader< + std::vector + >(reader); + } + + return std::make_pair( + std::move(*deserialized), + common::nullopt + ); +} + +// endregion De-serialize primitives + +namespace properties { + +enum class OfMyClass : std::uint32_t { + +}; // enum class OfMyClass + +enum class OfListOfPrimitives : std::uint32_t { + kStrings = 0, + kIntegers = 1, + kBooleans = 2, + kClasses = 3 +}; // enum class OfListOfPrimitives + +const std::unordered_map< + std::string, + OfMyClass +> kMapOfMyClass = { + +}; + +const std::unordered_map< + std::string, + OfListOfPrimitives +> kMapOfListOfPrimitives = { + { + "strings", + OfListOfPrimitives::kStrings + }, + { + "integers", + OfListOfPrimitives::kIntegers + }, + { + "booleans", + OfListOfPrimitives::kBooleans + }, + { + "classes", + OfListOfPrimitives::kClasses + } +}; + +} // namespace properties + +template < + typename T, + typename std::enable_if< + std::is_base_of::value + >::type* +> +std::pair< + common::optional >, + common::optional +> MyClassFromSequence( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in MyClassFromSequence. " + "MyClassFromSequence expects no reader error at entry." + ); + } + #endif + + common::optional error; + + error = SkipBof(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + while (true) { + error = SkipWhitespace(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + if (reader.node().kind() == NodeKind::Stop) { + // NOTE (mristin): + // We reached a closing element of an instance, so we know that + // the sequence ended. + break; + } else if (reader.node().kind() != NodeKind::Start) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening a property " + L"of IMyClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string name( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(reader.node()).name + ); + + // NOTE (mristin): + // We consume the start element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + auto it = properties::kMapOfMyClass.find( + name + ); + if (it == properties::kMapOfMyClass.end()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening a property " + L"of IMyClass, " + L"but got a start element " + L"which does not correspond to any of its properties: <", + common::Utf8ToWstring(name), + L">" + ) + ); + } + + const properties::OfMyClass property( + it->second + ); + + switch (property) { + default: + throw std::logic_error( + common::Concat( + "Unexpected properties literal of " + "properties::OfMyClass: ", + std::to_string( + static_cast(property) + ) + ) + ); + } + + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + if (!IsStopNodeWithName(reader.node(), name)) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing the property " + L"of IMyClass, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + // NOTE (mristin): + // We consume the stop element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + } + + return std::make_pair( + common::make_optional< + std::shared_ptr + >( + // NOTE (mristin): + // We deliberately do not use std::make_shared here to avoid an unnecessary + // upcast. + new types::MyClass() + ), + common::nullopt + ); +} + +template < + typename T, + typename std::enable_if< + std::is_base_of::value + >::type* +> +std::pair< + common::optional >, + common::optional +> ListOfPrimitivesFromSequence( + ReaderMergingText& reader +) { + #ifdef DEBUG + if (reader.node().kind() == NodeKind::Error) { + throw std::logic_error( + "Unexpected unhandled XML error in ListOfPrimitivesFromSequence. " + "ListOfPrimitivesFromSequence expects no reader error at entry." + ); + } + #endif + + common::optional error; + + error = SkipBof(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + // region Initialization + + common::optional > the_strings; + + common::optional > the_integers; + + common::optional > the_booleans; + + common::optional< + std::vector< + std::shared_ptr + > + > the_classes; + + // endregion Initialization + + while (true) { + error = SkipWhitespace(reader); + if (error.has_value()) { + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + if (reader.node().kind() == NodeKind::Stop) { + // NOTE (mristin): + // We reached a closing element of an instance, so we know that + // the sequence ended. + break; + } else if (reader.node().kind() != NodeKind::Start) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening a property " + L"of IListOfPrimitives, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + } + + const std::string name( + static_cast< // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + const StartNode& + >(reader.node()).name + ); + + // NOTE (mristin): + // We consume the start element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + auto it = properties::kMapOfListOfPrimitives.find( + name + ); + if (it == properties::kMapOfListOfPrimitives.end()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + common::Concat( + L"Expected a start element opening a property " + L"of IListOfPrimitives, " + L"but got a start element " + L"which does not correspond to any of its properties: <", + common::Utf8ToWstring(name), + L">" + ) + ); + } + + const properties::OfListOfPrimitives property( + it->second + ); + + switch (property) { + case properties::OfListOfPrimitives::kStrings: { + if (reader.node().kind() == NodeKind::Stop) { + the_strings = std::vector< + std::wstring + >(); + } else { + std::deque< + std::wstring + > items; + size_t i = 0; + + while (true) { + common::optional< + std::wstring + > item; + + std::tie( + item, + error + ) = DeserializeWstring(reader); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique(i) + ); + break; + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + break; + } + + items.emplace_back(*item); + + if (reader.node().kind() == NodeKind::Stop) { + break; + } + + ++i; + } + + if (!error.has_value()) { + the_strings = std::vector< + std::wstring + >(); + the_strings->reserve(items.size()); + + for (auto& item : items) { + the_strings->emplace_back( + std::move(item) + ); + } + } + } + break; + } + case properties::OfListOfPrimitives::kIntegers: { + if (reader.node().kind() == NodeKind::Stop) { + the_integers = std::vector< + int64_t + >(); + } else { + std::deque< + int64_t + > items; + size_t i = 0; + + while (true) { + common::optional< + int64_t + > item; + + std::tie( + item, + error + ) = DeserializeInt64(reader); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique(i) + ); + break; + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + break; + } + + items.emplace_back(*item); + + if (reader.node().kind() == NodeKind::Stop) { + break; + } + + ++i; + } + + if (!error.has_value()) { + the_integers = std::vector< + int64_t + >(); + the_integers->reserve(items.size()); + + for (auto& item : items) { + the_integers->emplace_back( + std::move(item) + ); + } + } + } + break; + } + case properties::OfListOfPrimitives::kBooleans: { + if (reader.node().kind() == NodeKind::Stop) { + the_booleans = std::vector< + bool + >(); + } else { + std::deque< + bool + > items; + size_t i = 0; + + while (true) { + common::optional< + bool + > item; + + std::tie( + item, + error + ) = DeserializeBool(reader); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique(i) + ); + break; + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + break; + } + + items.emplace_back(*item); + + if (reader.node().kind() == NodeKind::Stop) { + break; + } + + ++i; + } + + if (!error.has_value()) { + the_booleans = std::vector< + bool + >(); + the_booleans->reserve(items.size()); + + for (auto& item : items) { + the_booleans->emplace_back( + std::move(item) + ); + } + } + } + break; + } + case properties::OfListOfPrimitives::kClasses: { + if (reader.node().kind() == NodeKind::Stop) { + the_classes = std::vector< + std::shared_ptr + >(); + } else { + std::deque< + std::shared_ptr + > items; + size_t i = 0; + + while (true) { + common::optional< + std::shared_ptr + > item; + + std::tie( + item, + error + ) = MyClassFromElement(reader); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique(i) + ); + break; + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + break; + } + + items.emplace_back(*item); + + if (reader.node().kind() == NodeKind::Stop) { + break; + } + + ++i; + } + + if (!error.has_value()) { + the_classes = std::vector< + std::shared_ptr + >(); + the_classes->reserve(items.size()); + + for (auto& item : items) { + the_classes->emplace_back( + std::move(item) + ); + } + } + } + break; + } + default: + throw std::logic_error( + common::Concat( + "Unexpected properties literal of " + "properties::OfListOfPrimitives: ", + std::to_string( + static_cast(property) + ) + ) + ); + } + + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + if (!IsStopNodeWithName(reader.node(), name)) { + error = DeserializationError( + common::Concat( + L"Expected a stop element closing the property " + L"of IListOfPrimitives, but got ", + NodeToHumanReadableWstring(reader.node()) + ) + ); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + + // NOTE (mristin): + // We consume the stop element. + reader.Read(); + + if (reader.node().kind() == NodeKind::Error) { + error = DeserializationErrorFromReader(reader); + + PrependElementSegmentToDeserializationError( + name, + *error + ); + + return NoInstanceAndDeserializationError< + std::shared_ptr + >( + std::move(*error) + ); + } + } + + // region Check required properties + + if (!the_strings.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + L"The required property strings is missing" + ); + } + + if (!the_integers.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + L"The required property integers is missing" + ); + } + + if (!the_booleans.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + L"The required property booleans is missing" + ); + } + + if (!the_classes.has_value()) { + return NoInstanceAndDeserializationErrorWithCause< + std::shared_ptr + >( + L"The required property classes is missing" + ); + } + + // endregion Check required properties + + return std::make_pair( + common::make_optional< + std::shared_ptr + >( + // NOTE (mristin): + // We deliberately do not use std::make_shared here to avoid an unnecessary + // upcast. + new types::ListOfPrimitives( + std::move(*the_strings), + std::move(*the_integers), + std::move(*the_booleans), + std::move(*the_classes) + ) + ), + common::nullopt + ); +} + +common::expected< + std::shared_ptr, + DeserializationError +> From( + std::istream& is, + const ReadingOptions& options +) { + ReaderMergingText reader(is, options); + + reader.Initialize(); + if (reader.node().kind() == NodeKind::Error) { + return common::make_unexpected( + DeserializationErrorFromReader(reader) + ); + } + + common::optional< + std::shared_ptr + > instance; + + common::optional error; + + std::tie( + instance, + error + ) = ClassFromElement(reader); + + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + error = CheckReaderAtEof(reader); + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + return std::move(*instance); +} + +common::expected< + std::shared_ptr, + DeserializationError +> MyClassFrom( + std::istream& is, + const ReadingOptions& options +) { + ReaderMergingText reader(is, options); + + reader.Initialize(); + if (reader.node().kind() == NodeKind::Error) { + return common::make_unexpected( + DeserializationErrorFromReader(reader) + ); + } + + common::optional< + std::shared_ptr + > instance; + + common::optional error; + + std::tie( + instance, + error + ) = MyClassFromElement(reader); + + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + error = CheckReaderAtEof(reader); + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + return std::move(*instance); +} + +common::expected< + std::shared_ptr, + DeserializationError +> ListOfPrimitivesFrom( + std::istream& is, + const ReadingOptions& options +) { + ReaderMergingText reader(is, options); + + reader.Initialize(); + if (reader.node().kind() == NodeKind::Error) { + return common::make_unexpected( + DeserializationErrorFromReader(reader) + ); + } + + common::optional< + std::shared_ptr + > instance; + + common::optional error; + + std::tie( + instance, + error + ) = ListOfPrimitivesFromElement(reader); + + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + error = SkipWhitespace(reader); + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + error = CheckReaderAtEof(reader); + if (error.has_value()) { + return common::make_unexpected( + std::move(*error) + ); + } + + return std::move(*instance); +} + +// endregion De-serialization + +// region Serialization + +/** + * Represent a serialization error. + * + * We use this error internally to avoid unnecessary stack unwinding, + * but throw the \ref SerializationException at the final site of + * the serialization for the user. + */ +struct SerializationError { + /** + * Human-readable description of the error + */ + std::wstring cause; + + /** + * Path to the value that caused the error + */ + iteration::Path path; + + explicit SerializationError( + std::wstring a_cause + ) : + cause(std::move(a_cause)) { + // Intentionally empty. + } +}; // struct SerializationError + +const std::wstring kTheOutputStreamIsInABadState( + L"The output stream is in a bad state." + ); + +/** + * Check that the output stream is not in a bad state. If so, create an error. + */ +common::optional CheckOstreamState( + const std::ostream& os +) { + if (os.bad()) { + return common::make_optional( + kTheOutputStreamIsInABadState + ); + } + + return common::nullopt; +} + +// region SerializationException + +std::string RenderSerializationErrorMessage( + const std::wstring& cause, + const iteration::Path& path +) { + return common::WstringToUtf8( + common::Concat( + L"Serialization failed at ", + path.ToWstring(), + L": ", + cause + ) + ); +} + +SerializationException::SerializationException( + std::wstring cause +) : + cause_(std::move(cause)), + path_(), + msg_(RenderSerializationErrorMessage(cause, path_)) { + // Intentionally empty. +} + +SerializationException::SerializationException( + std::wstring cause, + iteration::Path path +) : + cause_(std::move(cause)), + path_(std::move(path)), + msg_(RenderSerializationErrorMessage(cause, path)) { + // Intentionally empty. +} + +const char* SerializationException::what() const noexcept { + return msg_.c_str(); +} + +const std::wstring& SerializationException::cause() const noexcept { + return cause_; +} + +const iteration::Path& SerializationException::path() const noexcept { + return path_; +} + +// endregion SerializationException + +// region SelfClosingWriter + +/** + * \brief Write XML nodes to the UTF-8-encoded output stream. + * + * The start elements are put on hold until we observe a text, a stop element or + * end-of-input. This allows us to continuously shorten the XML elements to self-closing + * tags. + * + * The prefix is appended to each element name. If you do not need the prefix, + * specify it as empty string. In most cases, you put a colon, `:` at the end of + * the prefix. + * + * Each writing method captures any errors and obvious exceptions as + * serialization errors. + * + * Use \ref error() to check if there is any error. + */ +class SelfClosingWriter { + public: + SelfClosingWriter( + std::ostream& os, + std::string prefix + ); + + /** + * Queue a start element for an eventual write. + */ + void StartElement( + std::string name + ); + + /** + * Write a stop element. + * + * If there is a pending start element with no content, shorten it to + * a self-closing XML element. + */ + void StopElement( + const std::string& name + ); + + /** + * \brief Serialize the given boolean to an xs:bool value. + * + * We explicitly write longer text, `true` and `false`, to make the values explicit, + * and not potentially confusing with numbers, in the XML. + */ + void SerializeBool( + bool value + ); + + /** + * \brief Serialize the given number to an xs:long value. + * + * We do not check that the number is within a range representable as 64-bit + * floats, as the value can be de-serialized correctly from XML. However, this + * means that XML and JSON serializations are not interoperable. If you need + * interoperability, you have to ensure that range yourself (e.g., through + * \ref validation, see also + * https://github.com/aas-core-works/aas-core-meta/issues/298). + */ + void SerializeInt64( + int64_t value + ); + + /** + * \brief Serialize the given number to an xs:double value. + */ + void SerializeDouble( + double value + ); + + /** + * \brief Write the text while escaping special characters for XML. + */ + void SerializeWstring( + const std::wstring& text + ); + + /** + * \brief Write the text while escaping special characters for XML. + */ + void SerializeString( + const std::string& text + ); + + /** + * \brief Encode bytes to Base64 and write them. + */ + void SerializeByteArray( + const std::vector& byte_array + ); + + /** + * Finish and flush any pending start nodes. + */ + void Finish(); + + /** + * Get an error, if any, caught during the serialization. + */ + const common::optional& error() const; + + /** + * Transfer the ownership of the error. + */ + common::optional&& move_error(); + + private: + std::ostream& os_; + std::string prefix_; + common::optional error_; + common::optional pending_start_wo_text_; + + /** + * \brief Escape the given text to XML. + * + * Return nothing if no escaping was needed. + */ + static common::optional EscapeForXml( + const std::wstring& text + ); + + /** + * \brief Escape the given text to XML. + * + * Return nothing if no escaping was needed. + */ + static common::optional EscapeForXml( + const std::string& text + ); + + void WritePendingStartElementIfAvailable(); + + /** + * Write the text without any XML escaping or flushing of pending start elements. + */ + void WriteStringWithoutEscapingNorFlushing( + const std::string& text + ); +}; // class SelfClosingWriter + +SelfClosingWriter::SelfClosingWriter( + std::ostream& os, + std::string prefix +) : + os_(os), + prefix_(std::move(prefix)) { + // Intentionally empty. +} + +void SelfClosingWriter::StartElement( + std::string name +) { + #ifdef DEBUG + if (error_.has_value()) { + throw std::logic_error( + "You are trying to queue a start element with a SelfClosingWriter " + "which caught an error." + ); + #endif + + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + pending_start_wo_text_ = std::move(name); +} + +void SelfClosingWriter::StopElement( + const std::string& name +) { + #ifdef DEBUG + if (error_.has_value()) { + throw std::logic_error( + "You are trying to write a stop element with a SelfClosingWriter " + "which caught an error before." + ); + #endif + + if (pending_start_wo_text_.has_value()) { + #ifdef DEBUG + if (*pending_start_wo_text_ != name) { + throw std::logic_error( + common::Concat( + "The start element <", + *pending_start_wo_text_, + "> is pending for writing, " + "but you are trying to write a stop element " + ) + ); + } + #endif + + pending_start_wo_text_ = common::nullopt; + + WriteStringWithoutEscapingNorFlushing( + common::Concat( + "<", + prefix_, + name, + " />" + ) + ); + } else { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + WriteStringWithoutEscapingNorFlushing( + common::Concat( + "" + ) + ); + } +} + +void SelfClosingWriter::SerializeBool( + bool value +) { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + WriteStringWithoutEscapingNorFlushing( + value ? "true" : "false" + ); +} + +void SelfClosingWriter::SerializeInt64( + int64_t value +) { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + WriteStringWithoutEscapingNorFlushing( + std::to_string(value) + ); +} + +void SelfClosingWriter::SerializeDouble( + double value +) { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + // NOTE (mristin): + // We handle edge values infinity and not-a-number explicitly here + // as some C/C++ implementations might not convert them to XML-conformant + // strings. + + if (std::isinf(value)) { + if (value < 0) { + WriteStringWithoutEscapingNorFlushing("-INF"); + } else { + WriteStringWithoutEscapingNorFlushing("INF"); + } + } else if(std::isnan(value)) { + WriteStringWithoutEscapingNorFlushing("NaN"); + } else { + WriteStringWithoutEscapingNorFlushing( + std::to_string(value) + ); + } +} + +void SelfClosingWriter::SerializeString( + const std::string& text +) { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + // NOTE (mristin): + // We optimize here for short and long texts, respectively. + // The main assumption is that the short texts can be escaped and converted + // in one go, while the longer texts need to be converted in chunks. + + if (text.size() < 1024) { + common::optional escaped = EscapeForXml(text); + + if (escaped.has_value()) { + WriteStringWithoutEscapingNorFlushing( + *escaped + ); + return; + } else { + WriteStringWithoutEscapingNorFlushing( + text + ); + return; + } + } + + size_t start = 0; + while (start < text.size()) { + const size_t end = std::min(start + 1024, text.size()); + const size_t chunk_size = end - start; + + // NOTE (mristin): + // We assume that making short copies of text substrings does not hurt + // the performance here, but makes the code more readable. + + const std::string chunk = text.substr(start, chunk_size); + + common::optional escaped = EscapeForXml(chunk); + + if (escaped.has_value()) { + WriteStringWithoutEscapingNorFlushing( + *escaped + ); + } else { + WriteStringWithoutEscapingNorFlushing( + chunk + ); + } + + if (error_.has_value()) { + return; + } + + start += chunk_size; + } +} + +void SelfClosingWriter::SerializeWstring( + const std::wstring& text +) { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + // NOTE (mristin): + // We optimize here for short and long texts, respectively. + // The main assumption is that the short texts can be escaped and converted + // in one go, while the longer texts need to be converted in chunks. + + if (text.size() < 1024) { + common::optional escaped = EscapeForXml(text); + + if (escaped.has_value()) { + WriteStringWithoutEscapingNorFlushing( + common::WstringToUtf8(*escaped) + ); + return; + } else { + WriteStringWithoutEscapingNorFlushing( + common::WstringToUtf8(text) + ); + return; + } + } + + size_t start = 0; + while (start < text.size()) { + const size_t end = std::min(start + 1024, text.size()); + const size_t chunk_size = end - start; + + // NOTE (mristin): + // We assume that making short copies of text substrings does not hurt + // the performance here, but makes the code more readable. + + const std::wstring chunk = text.substr(start, chunk_size); + + common::optional escaped = EscapeForXml(chunk); + + if (escaped.has_value()) { + WriteStringWithoutEscapingNorFlushing( + common::WstringToUtf8(*escaped) + ); + } else { + WriteStringWithoutEscapingNorFlushing( + common::WstringToUtf8(chunk) + ); + } + + if (error_.has_value()) { + return; + } + + start += chunk_size; + } +} + +void SelfClosingWriter::SerializeByteArray( + const std::vector& byte_array +) { + WritePendingStartElementIfAvailable(); + if (error_.has_value()) { + return; + } + + // NOTE (mristin): + // We optimize here for short and long byte arrays, respectively. + // The main assumption is that the short texts can be escaped and converted + // in one go, while the longer texts need to be converted in chunks. + // + // Optimally, we would write an encoding function such that it encodes directly + // to the output stream. As we lack the time resources for that at the moment, + // we go for the compromise with one pass and chunking, respectively. + + if (byte_array.size() <= 1536) { + WriteStringWithoutEscapingNorFlushing( + stringification::Base64Encode(byte_array) + ); + return; + } + + // NOTE (mristin): + // We assume here that making copies of small sub-arrays does not hurt + // the performance, but makes the code substantially more readable. + + size_t start = 0; + while (start < byte_array.size()) { + // NOTE (mristin): + // We pick a multiple of 3 for the chunk size in order to make the encoding + // of chunking identical to the output as we encoded all bytes at the same time. + // + // See: https://stackoverflow.com/questions/7920780/is-it-possible-to-base64-encode-a-file-in-chunks + + const size_t end = std::min(start + 1536, byte_array.size()); + + const std::vector chunk( + byte_array.begin() + start, + byte_array.begin() + end + ); + + WriteStringWithoutEscapingNorFlushing( + stringification::Base64Encode(chunk) + ); + if (error_.has_value()) { + return; + } + } +} + +void SelfClosingWriter::Finish() { + WritePendingStartElementIfAvailable(); +} + +const common::optional& SelfClosingWriter::error() const { + return error_; +} + +common::optional&& SelfClosingWriter::move_error() { + return std::move(error_); +} + +common::optional SelfClosingWriter::EscapeForXml( + const std::wstring& text +) { + size_t out_len = 0; + + // NOTE (mristin): + // We use sizeof on *strings* instead of *wide strings* to get + // the number of *characters*. Otherwise, if we used wide strings, + // we would obtain the wrong number of characters as we would count + // bytes instead of characters with `sizeof`, which differ in wide strings + // due to encoding. + + for (wchar_t character : text ) { + switch (character) { + case L'&': { + out_len += sizeof("&"); + break; + } + case L'<': { + out_len += sizeof("<"); + break; + } + case L'>': { + out_len += sizeof(">"); + break; + } + case L'"': { + out_len += sizeof("""); + break; + } + case L'\'': { + out_len += sizeof("'"); + break; + } + default: + ++out_len; + break; + } + } + + // NOTE (mristin): + // We assume here that XML encoding is always *longer* than + // the original text. + + if (out_len == text.size()) { + return common::nullopt; + } + + std::wstring out; + out.reserve(out_len); + + for (wchar_t character : text ) { + switch (character) { + case L'&': + out.append(L"&"); + break; + case L'<': + out.append(L"<"); + break; + case L'>': + out.append(L">"); + break; + case L'"': + out.append(L"""); + break; + case L'\'': + out.append(L"'"); + break; + default: + out.push_back(character); + break; + } + } + + return common::make_optional( + std::move(out) + ); +} + +common::optional SelfClosingWriter::EscapeForXml( + const std::string& text +) { + size_t out_len = 0; + + for (char character : text ) { + switch (character) { + case '&': { + out_len += sizeof("&"); + break; + } + case '<': { + out_len += sizeof("<"); + break; + } + case '>': { + out_len += sizeof(">"); + break; + } + case '"': { + out_len += sizeof("""); + break; + } + case '\'': { + out_len += sizeof("'"); + break; + } + default: + ++out_len; + break; + } + } + + // NOTE (mristin): + // We assume here that XML encoding is always *longer* than + // the original text. + + if (out_len == text.size()) { + return common::nullopt; + } + + std::string out; + out.reserve(out_len); + + for (char character : text ) { + switch (character) { + case '&': + out.append("&"); + break; + case '<': + out.append("<"); + break; + case '>': + out.append(">"); + break; + case '"': + out.append("""); + break; + case '\'': + out.append("'"); + break; + default: + out.push_back(character); + break; + } + } + + return common::make_optional( + std::move(out) + ); +} + +void SelfClosingWriter::WritePendingStartElementIfAvailable() { + if (!pending_start_wo_text_.has_value()) { + return; + } + + WriteStringWithoutEscapingNorFlushing( + common::Concat( + "<", + prefix_, + *pending_start_wo_text_, + ">" + ) + ); + + pending_start_wo_text_ = common::nullopt; +} + +void SelfClosingWriter::WriteStringWithoutEscapingNorFlushing( + const std::string& text +) { + #ifdef DEBUG + if (error_.has_value()) { + throw std::logic_error( + "You are trying to write to a SelfClosingWriter which " + "caught an error" + ); + } + #endif + + if (os_.bad()) { + error_ = common::make_optional( + kTheOutputStreamIsInABadState + ); + return; + } + + os_ << text; + + if (os_.bad()) { + error_ = common::make_optional( + kTheOutputStreamIsInABadState + ); + return; + } +} + +// endregion SelfClosingWriter + +/** + * \brief Serialize \p that instance as a sequence of XML elements. + * + * Each XML element corresponds to a property. + * + * \param that instance to be serialized + * \param writer to write to + * \return error, if any + */ +common::optional SerializeMyClassAsSequence( + const types::IMyClass& that, + SelfClosingWriter& writer +); + +/** + * Serialize \p that instance to an XML element + * ``. + * + * \param that instance to be serialized + * \return an error, if any + */ +common::optional SerializeMyClassAsElement( + const types::IMyClass& that, + SelfClosingWriter& writer +); + +/** + * \brief Serialize \p that instance as a sequence of XML elements. + * + * Each XML element corresponds to a property. + * + * \param that instance to be serialized + * \param writer to write to + * \return error, if any + */ +common::optional SerializeListOfPrimitivesAsSequence( + const types::IListOfPrimitives& that, + SelfClosingWriter& writer +); + +/** + * Serialize \p that instance to an XML element + * ``. + * + * \param that instance to be serialized + * \return an error, if any + */ +common::optional SerializeListOfPrimitivesAsElement( + const types::IListOfPrimitives& that, + SelfClosingWriter& writer +); + +/** + * \brief Serialize \p that instance as a sequence of XML elements. + * + * Each XML element corresponds to a property. + * + * \param that instance to be serialized + * \param writer to write to + * \return error, if any + */ +common::optional SerializeMyClassAsSequence( + const types::IMyClass& that, + SelfClosingWriter& writer +) { + return common::nullopt; +} + +common::optional SerializeMyClassAsElement( + const types::IMyClass& that, + SelfClosingWriter& writer +) { + common::optional error; + + writer.StartElement( + "myClass" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + + error = SerializeMyClassAsSequence( + that, + writer + ); + if (error.has_value()) { + return error; + } + + writer.StopElement( + "myClass" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + + writer.Finish(); + if (writer.error().has_value()) { + return writer.move_error(); + } + + return common::nullopt; +} + +/** + * \brief Serialize \p that instance as a sequence of XML elements. + * + * Each XML element corresponds to a property. + * + * \param that instance to be serialized + * \param writer to write to + * \return error, if any + */ +common::optional SerializeListOfPrimitivesAsSequence( + const types::IListOfPrimitives& that, + SelfClosingWriter& writer +) { + common::optional error; + + const std::vector& the_strings( + that.strings() + ); + writer.StartElement( + "strings" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + for (size_t i = 0; i < the_strings.size(); ++i) { + std::wstring item( + the_strings[i] + ); + + error = DeserializeWstring( + *item, + writer + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + i + ) + ); + + break; + } + } + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kStrings + ) + ); + + return error; + } + writer.StopElement( + "strings" + ); + if (writer.error().has_value()) { + error = writer.move_error(); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kStrings + ) + ); + + return error; + } + + const std::vector& the_integers( + that.integers() + ); + writer.StartElement( + "integers" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + for (size_t i = 0; i < the_integers.size(); ++i) { + int64_t item( + the_integers[i] + ); + + error = DeserializeInt64( + *item, + writer + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + i + ) + ); + + break; + } + } + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kIntegers + ) + ); + + return error; + } + writer.StopElement( + "integers" + ); + if (writer.error().has_value()) { + error = writer.move_error(); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kIntegers + ) + ); + + return error; + } + + const std::vector& the_booleans( + that.booleans() + ); + writer.StartElement( + "booleans" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + for (size_t i = 0; i < the_booleans.size(); ++i) { + bool item( + the_booleans[i] + ); + + error = DeserializeBool( + *item, + writer + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + i + ) + ); + + break; + } + } + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kBooleans + ) + ); + + return error; + } + writer.StopElement( + "booleans" + ); + if (writer.error().has_value()) { + error = writer.move_error(); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kBooleans + ) + ); + + return error; + } + + const std::vector< + std::shared_ptr + >& the_classes( + that.classes() + ); + writer.StartElement( + "classes" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + for (size_t i = 0; i < the_classes.size(); ++i) { + const std::shared_ptr& item( + the_classes[i] + ); + + error = SerializeMyClassAsElement( + *item, + writer + ); + + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + i + ) + ); + + break; + } + } + if (error.has_value()) { + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kClasses + ) + ); + + return error; + } + writer.StopElement( + "classes" + ); + if (writer.error().has_value()) { + error = writer.move_error(); + + error->path.segments.emplace_front( + common::make_unique( + iteration::Property::kClasses + ) + ); + + return error; + } + + writer.Finish(); + if (writer.error().has_value()) { + return writer.move_error(); + } + + return common::nullopt; +} + +common::optional SerializeListOfPrimitivesAsElement( + const types::IListOfPrimitives& that, + SelfClosingWriter& writer +) { + common::optional error; + + writer.StartElement( + "listOfPrimitives" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + + error = SerializeListOfPrimitivesAsSequence( + that, + writer + ); + if (error.has_value()) { + return error; + } + + writer.StopElement( + "listOfPrimitives" + ); + if (writer.error().has_value()) { + return writer.move_error(); + } + + writer.Finish(); + if (writer.error().has_value()) { + return writer.move_error(); + } + + return common::nullopt; +} + +void Serialize( + const types::IClass& that, + const WritingOptions& options, + std::ostream& os +) { + if (options.write_declaration) { + os << "\n"; + if (os.bad()) { + throw SerializationException( + kTheOutputStreamIsInABadState + ); + } + } + + SelfClosingWriter writer( + os, + options.prefix + ); + + common::optional error; + + // NOTE (mristin): + // Instead of using `Serialize*AsElement`, we write the root XML element + // in this functions so that we check for the XML namespace only once, namely + // here. Otherwise, we would have a condition check in every nested + // `Serialize*AsElement` which could cause a significant efficiency hit. + + // NOTE (mristin): + // The dynamic casts are necessary due to virtual inheritance. Otherwise, + // we would have used static casts. + + switch (that.model_type()) { + case types::ModelType::kMyClass: + if (options.write_namespace) { + os << ( + "" + ); + } else { + os << ""; + } + + error = CheckOstreamState(os); + if (error.has_value()) { + break; + } + + error = SerializeMyClassAsSequence( + dynamic_cast< + const types::IMyClass& + >(that), + writer + ); + if (error.has_value()) { + break; + } + + os << ""; + + error = CheckOstreamState(os); + if (error.has_value()) { + break; + } + + break; + case types::ModelType::kListOfPrimitives: + if (options.write_namespace) { + os << ( + "" + ); + } else { + os << ""; + } + + error = CheckOstreamState(os); + if (error.has_value()) { + break; + } + + error = SerializeListOfPrimitivesAsSequence( + dynamic_cast< + const types::IListOfPrimitives& + >(that), + writer + ); + if (error.has_value()) { + break; + } + + os << ""; + + error = CheckOstreamState(os); + if (error.has_value()) { + break; + } + + break; + default: + throw std::invalid_argument( + common::Concat( + "Invalid model type: ", + stringification::to_string(that.model_type()) + ) + ); + } + + if (error.has_value()) { + throw SerializationException( + std::move(error->cause), + std::move(error->path) + ); + } +} + +// endregion Serialization + +} // namespace xmlization +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. diff --git a/test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.hpp b/test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.hpp new file mode 100644 index 000000000..c508fc181 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/expected_output/xmlization.hpp @@ -0,0 +1,290 @@ +#ifndef AAS_CORE_AAS_3_0_XMLIZATION_GUARD_ +#define AAS_CORE_AAS_3_0_XMLIZATION_GUARD_ + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#include "aas_core/aas_3_0/common.hpp" +#include "aas_core/aas_3_0/iteration.hpp" +#include "aas_core/aas_3_0/types.hpp" + +#pragma warning(push, 0) +#include +#include +#include +#pragma warning(pop) + +namespace aas_core { +namespace aas_3_0 { + +/** + * \defgroup xmlization De/serialize instances from and to XML. + * @{ + */ +namespace xmlization { + +/** + * Specify the expected XML namespace of all the XML elements. + */ +extern const std::string kNamespace; + +/** + * Represent a segment of an XPath to an erroneous value. + */ +class ISegment { + public: + /** + * \brief Convert the segment to a string in an XPath. + * + * The result is escaped such that it can be directly inserted + * into an XPath. + */ + virtual std::wstring ToWstring() const = 0; + + virtual std::unique_ptr Clone() const = 0; + + virtual ~ISegment() = default; +}; // class ISegment + +/** + * Represent an element on an XPath to the erroneous value. + */ +struct ElementSegment : public ISegment { + /** + * \brief Name of the XML element, without the namespace + * + * We deliberately omit the namespace in the tag names. If you want to actually + * query with the resulting XPath, you have to insert the namespaces manually. + * We did not know how to include the namespace in a meaningful way, as XPath + * assumes namespace prefixes to be defined outside of the document. + * At least the path thus rendered is informative, and you should be able to + * descend it manually. + */ + std::wstring name; + + ElementSegment( + std::wstring a_name + ); + + std::wstring ToWstring() const override; + + std::unique_ptr Clone() const override; + + ~ElementSegment() override = default; +}; // struct ElementSegment + +/** + * Represent an element in a sequence on an XPath to the erroneous value. + */ +struct IndexSegment : public ISegment { + /** + * Index of the element in the sequence + */ + size_t index; + + explicit IndexSegment( + size_t an_index + ); + + std::wstring ToWstring() const override; + + std::unique_ptr Clone() const override; + + ~IndexSegment() override = default; +}; // struct IndexSegment + +/** + * Represent the relative XPath to the erroneous element. + */ +struct Path { + std::deque > segments; + + Path(); + Path(const Path& other); + Path(Path&& other); + Path& operator=(const Path& other); + Path& operator=(Path&& other); + + std::wstring ToWstring() const; +}; // struct Path + +// region De-serialization + +/** + * Represent a de-serialization error. + */ +struct DeserializationError { + /** + * Human-readable description of the error + */ + std::wstring cause; + + /** + * Path to the erroneous value + */ + Path path; + + explicit DeserializationError(std::wstring a_cause); + DeserializationError(std::wstring a_cause, Path a_path); +}; // struct DeserializationError + +struct ReadingOptions { + /** + * No XML attributes are expected in XML elements. + * Usually, attributes are considered errors and reported as such. However, + * some implementations add their own custom attributes, and we sometimes + * still want to parse such XML. If `additional_attributes` is set, + * the unexpected XML attributes will be ignored during parsing, and not + * reported. + */ + bool additional_attributes = false; + + /** + * Size of the chunk to be read from the input stream and passed to + * the XML parser. + */ + size_t buffer_size = 1024; +}; // struct ReadingOptions + +/** + * Deserialize the instance from an XML read from the stream \p is. + * + * \param is stream of ASCII, ISO-8859-1 or UTF-8-encoded characters to read XML from + * \param options reading options to be tweaked for special cases. The defaults should + * work in most cases. + * \return the parsed instance, or an error if any + */ +common::expected< + std::shared_ptr, + DeserializationError +> From( + std::istream& is, + const ReadingOptions& options = {} +); + +/** + * Deserialize an instance of types::IMyClass from an XML + * read from the stream \p is. + * + * \param is stream to read XML from + * \param options reading options to be tweaked for special cases. The defaults should + * work in most cases. + * \return the parsed types::IMyClass, or an error if any + */ +common::expected< + std::shared_ptr, + DeserializationError +> MyClassFrom( + std::istream& is, + const ReadingOptions& options = {} +); + +/** + * Deserialize an instance of types::IListOfPrimitives from an XML + * read from the stream \p is. + * + * \param is stream to read XML from + * \param options reading options to be tweaked for special cases. The defaults should + * work in most cases. + * \return the parsed types::IListOfPrimitives, or an error if any + */ +common::expected< + std::shared_ptr, + DeserializationError +> ListOfPrimitivesFrom( + std::istream& is, + const ReadingOptions& options = {} +); + +// endregion Deserialization + +// region Serialization + +/** + * Represent an error in the serialization of an instance to XML. + */ +class SerializationException : public std::exception { + public: + SerializationException( + std::wstring cause + ); + + SerializationException( + std::wstring cause, + iteration::Path path + ); + + const char* what() const noexcept override; + + const std::wstring& cause() const noexcept; + const iteration::Path& path() const noexcept; + + ~SerializationException() noexcept override = default; + + private: + const std::wstring cause_; + const iteration::Path path_; + const std::string msg_; +}; // class SerializationException + +/** + * \brief Customize how instances should be serialized to XML. + * + * We selected the defaults so that they can be used when you serialize to + * a file. + * + * Usually, you want to write the namespace at the root element, and no + * prefixes are written in the XML names. However, if you are embedding + * the XML in a larger XML structure, you specify the namespace + * aliases and then use them as XML name prefixes. The prefix usually ends + * with a full colon (`:`). + * + * We can not imagine in what situation you would want to write both + * the namespace and the prefix. Nevertheless, we allow for that + * possibility and do not throw any exception if you specify the both. + */ +struct WritingOptions { + /** + * If set, the XML declaration is written at the beginning. + */ + bool write_declaration = true; + + /** + * If set, the root XML element is written with the XML namespace + * set as the XML attribute `xmlns`. + */ + bool write_namespace = true; + + /** + * The prefix is prepended to the name of each XML element. + */ + std::string prefix = ""; +}; // struct WritingOptions + +/** + * \brief Serialize \p that instance to XML. + * + * \param that instance to be serialized + * \param options to be tweaked for special cases. The defaults should + * work in most cases. + * \param os The UTF8-encoded output stream where XML will be written + * \throw \ref SerializationException if \p that instance could not be serialized + */ +void Serialize( + const types::IClass& that, + const WritingOptions& options, + std::ostream& os +); + +// endregion Serialization + +} // namespace xmlization +/**@}*/ + +} // namespace aas_3_0 +} // namespace aas_core + +// This code has been automatically generated by aas-core-codegen. +// Do NOT edit or append. + +#endif // AAS_CORE_AAS_3_0_XMLIZATION_GUARD_ diff --git a/test_data/cpp/test_main/list_of_primitives/input/snippets/namespace.txt b/test_data/cpp/test_main/list_of_primitives/input/snippets/namespace.txt new file mode 100644 index 000000000..8a3f28b9a --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/input/snippets/namespace.txt @@ -0,0 +1 @@ +aas_core::aas_3_0 diff --git a/test_data/cpp/test_main/list_of_primitives/meta_model.py b/test_data/cpp/test_main/list_of_primitives/meta_model.py new file mode 100644 index 000000000..ed2060bd5 --- /dev/null +++ b/test_data/cpp/test_main/list_of_primitives/meta_model.py @@ -0,0 +1,28 @@ +from typing import List + + +class My_class: + pass + + +class List_of_primitives: + strings: List[str] + integers: List[int] + booleans: List[bool] + classes: List[My_class] + + def __init__( + self, + strings: List[str], + integers: List[int], + booleans: List[bool], + classes: List[My_class], + ) -> None: + self.strings = strings + self.integers = integers + self.booleans = booleans + self.classes = classes + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" diff --git a/tests/cpp/test_main.py b/tests/cpp/test_main.py index d05f72680..7004f6cb7 100644 --- a/tests/cpp/test_main.py +++ b/tests/cpp/test_main.py @@ -15,26 +15,29 @@ class Test_against_recorded(unittest.TestCase): - def test_cases(self) -> None: - repo_dir = pathlib.Path(os.path.realpath(__file__)).parent.parent.parent - - parent_case_dir = repo_dir / "test_data" / "cpp" / "test_main" - assert parent_case_dir.exists() and parent_case_dir.is_dir(), parent_case_dir - - for module in [aas_core_meta.v3]: - case_dir = parent_case_dir / module.__name__ - assert case_dir.is_dir(), case_dir - - assert ( - module.__file__ is not None - ), f"Expected the module {module!r} to have a __file__, but it has None" - model_pth = pathlib.Path(module.__file__) - assert model_pth.exists() and model_pth.is_file(), model_pth + _REPO_DIR = pathlib.Path(os.path.realpath(__file__)).parent.parent.parent + PARENT_CASE_DIR = _REPO_DIR / "test_data" / "cpp" / "test_main" - snippets_dir = case_dir / "input/snippets" + def test_cases(self) -> None: + assert ( + Test_against_recorded.PARENT_CASE_DIR.exists() + and Test_against_recorded.PARENT_CASE_DIR.is_dir() + ), f"{Test_against_recorded.PARENT_CASE_DIR=}" + + # fmt: off + test_cases = ( + tests.common.find_meta_models_in_parent_directory_of_test_cases_and_modules( + parent_case_dir=Test_against_recorded.PARENT_CASE_DIR, + aas_core_meta_modules=[aas_core_meta.v3] + ) + ) + # fmt: on + + for test_case in test_cases: + snippets_dir = test_case.case_dir / "input/snippets" assert snippets_dir.exists() and snippets_dir.is_dir(), snippets_dir - expected_output_dir = case_dir / "expected_output" + expected_output_dir = test_case.case_dir / "expected_output" with contextlib.ExitStack() as exit_stack: if tests.common.RERECORD: @@ -51,7 +54,7 @@ def test_cases(self) -> None: output_dir = pathlib.Path(tmp_dir.name) params = aas_core_codegen.main.Parameters( - model_path=model_pth, + model_path=test_case.model_path, target=aas_core_codegen.main.Target.CPP, snippets_dir=snippets_dir, output_dir=output_dir, @@ -123,27 +126,14 @@ def test_cases(self) -> None: f"The output file is missing: {output_pth}" ) - try: - output = output_pth.read_text(encoding="utf-8") - except Exception as exception: - raise RuntimeError( - f"Failed to read the output from {output_pth}" - ) from exception - if tests.common.RERECORD: - expected_pth.write_text(output, encoding="utf-8") + expected_pth.write_text( + output_pth.read_text(encoding="utf-8"), encoding="utf-8" + ) else: - try: - expected_output = expected_pth.read_text(encoding="utf-8") - except Exception as exception: - raise RuntimeError( - f"Failed to read the expected output " - f"from {expected_pth}" - ) from exception - self.assertEqual( - expected_output, - output, + expected_pth.read_text(encoding="utf-8"), + output_pth.read_text(encoding="utf-8"), f"The files {expected_pth} and {output_pth} do not match.", ) From 5363655e7710df8ceceed5f6634a4d259a3c2056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otto?= Date: Tue, 4 Feb 2025 14:54:24 +0100 Subject: [PATCH 7/7] Add XSD generation --- aas_core_codegen/xsd/main.py | 20 +++++++ .../expected_output/schema.xsd | 53 +++++++++++++++++++ .../expected_output/stdout.txt | 1 + .../input/snippets/root_element.xml | 8 +++ .../list_of_primitives/meta_model.py | 45 ++++++++++++++++ tests/xsd/test_main.py | 26 ++++----- 6 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 test_data/xsd/test_main/list_of_primitives/expected_output/schema.xsd create mode 100644 test_data/xsd/test_main/list_of_primitives/expected_output/stdout.txt create mode 100644 test_data/xsd/test_main/list_of_primitives/input/snippets/root_element.xml create mode 100644 test_data/xsd/test_main/list_of_primitives/meta_model.py diff --git a/aas_core_codegen/xsd/main.py b/aas_core_codegen/xsd/main.py index 67a49f09c..596eeefca 100644 --- a/aas_core_codegen/xsd/main.py +++ b/aas_core_codegen/xsd/main.py @@ -472,6 +472,26 @@ def _generate_xs_element_for_a_list_property( ) else: assert_never(our_type) + elif isinstance(type_anno.items, intermediate.PrimitiveTypeAnnotation): + xs_element_inner = ET.Element( + "xs:element", + { + "name": "v", + "type": _PRIMITIVE_MAP[type_anno.items.a_type], + "minOccurs": min_occurs, + "maxOccurs": max_occurs, + }, + ) + xs_sequence = ET.Element("xs:sequence") + xs_sequence.append(xs_element_inner) + + xs_complex_type = ET.Element("xs:complexType") + xs_complex_type.append(xs_sequence) + + xs_element = ET.Element( + "xs:element", {"name": naming.xml_property(prop.name)} + ) + xs_element.append(xs_complex_type) else: return None, Error( prop.parsed.node, diff --git a/test_data/xsd/test_main/list_of_primitives/expected_output/schema.xsd b/test_data/xsd/test_main/list_of_primitives/expected_output/schema.xsd new file mode 100644 index 000000000..b05c607d9 --- /dev/null +++ b/test_data/xsd/test_main/list_of_primitives/expected_output/schema.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_data/xsd/test_main/list_of_primitives/expected_output/stdout.txt b/test_data/xsd/test_main/list_of_primitives/expected_output/stdout.txt new file mode 100644 index 000000000..2d755fc5a --- /dev/null +++ b/test_data/xsd/test_main/list_of_primitives/expected_output/stdout.txt @@ -0,0 +1 @@ +Code generated to: diff --git a/test_data/xsd/test_main/list_of_primitives/input/snippets/root_element.xml b/test_data/xsd/test_main/list_of_primitives/input/snippets/root_element.xml new file mode 100644 index 000000000..ee0bfd97d --- /dev/null +++ b/test_data/xsd/test_main/list_of_primitives/input/snippets/root_element.xml @@ -0,0 +1,8 @@ + + + diff --git a/test_data/xsd/test_main/list_of_primitives/meta_model.py b/test_data/xsd/test_main/list_of_primitives/meta_model.py new file mode 100644 index 000000000..7de018dd8 --- /dev/null +++ b/test_data/xsd/test_main/list_of_primitives/meta_model.py @@ -0,0 +1,45 @@ +from typing import List +from icontract import DBC + +class Value_data_type(str, DBC): + """ + any XSD simple type as specified via :class:`Data_type_def_XSD` + """ + +class Data_type_def_XSD(Enum): + """ + Enumeration listing all XSD anySimpleTypes + """ + Boolean = "xs:boolean" + Date = "xs:date" + Integer = "xs:integer" + String = "xs:string" + +class My_class: + pass + + +class List_of_primitives: + foo: str + strings: List[str] + integers: List[int] + booleans: List[bool] + classes: List[My_class] + + def __init__( + self, + foo: str, + strings: List[str], + integers: List[int], + booleans: List[bool], + classes: List[My_class], + ) -> None: + self.foo = foo + self.strings = strings + self.integers = integers + self.booleans = booleans + self.classes = classes + + +__version__ = "dummy" +__xml_namespace__ = "https://dummy.com" diff --git a/tests/xsd/test_main.py b/tests/xsd/test_main.py index b2e6513bb..cd4a547a1 100644 --- a/tests/xsd/test_main.py +++ b/tests/xsd/test_main.py @@ -109,26 +109,26 @@ class Test_against_recorded(unittest.TestCase): _REPO_DIR = pathlib.Path(os.path.realpath(__file__)).parent.parent.parent PARENT_CASE_DIR = _REPO_DIR / "test_data" / "xsd" / "test_main" - def test_against_aas_core_meta(self) -> None: + def test_against_meta_models(self) -> None: assert ( Test_against_recorded.PARENT_CASE_DIR.exists() and Test_against_recorded.PARENT_CASE_DIR.is_dir() ), f"{Test_against_recorded.PARENT_CASE_DIR=}" - for module in [aas_core_meta.v3]: - case_dir = Test_against_recorded.PARENT_CASE_DIR / module.__name__ - assert case_dir.is_dir(), case_dir - - assert ( - module.__file__ is not None - ), f"Expected the module {module!r} to have a __file__, but it has None" - model_pth = pathlib.Path(module.__file__) - assert model_pth.exists() and model_pth.is_file(), model_pth + # fmt: off + test_cases = ( + tests.common.find_meta_models_in_parent_directory_of_test_cases_and_modules( + parent_case_dir=Test_against_recorded.PARENT_CASE_DIR, + aas_core_meta_modules=[aas_core_meta.v3] + ) + ) + # fmt: on - snippets_dir = case_dir / "input/snippets" + for test_case in test_cases: + snippets_dir = test_case.case_dir / "input/snippets" assert snippets_dir.exists() and snippets_dir.is_dir(), snippets_dir - expected_output_dir = case_dir / "expected_output" + expected_output_dir = test_case.case_dir / "expected_output" with contextlib.ExitStack() as exit_stack: if tests.common.RERECORD: @@ -145,7 +145,7 @@ def test_against_aas_core_meta(self) -> None: output_dir = pathlib.Path(tmp_dir.name) params = aas_core_codegen.main.Parameters( - model_path=model_pth, + model_path=test_case.model_path, target=aas_core_codegen.main.Target.XSD, snippets_dir=snippets_dir, output_dir=output_dir,